summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorNate Rosenblum <nater@maginatics.com>2014-11-17 09:46:48 -0800
committerRoger Meier <roger@apache.org>2014-12-13 21:22:47 +0100
commit3c5a788d8f243e23474b3ac09a795e4e15a8933f (patch)
tree0d84c0d641f8872cbfc230753f90ffa13c033e12 /compiler
parent714a9aa1c544508e430d1d74a39202fc784df947 (diff)
downloadthrift-3c5a788d8f243e23474b3ac09a795e4e15a8933f.tar.gz
THRIFT-2836 Add moveable_types option to C++ generator
Setting this option enables generation of MoveConstructible types, allowing types to be bound via move in std::bind. This is especially pleasant when using Thrift container types.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/cpp/src/generate/t_cpp_generator.cc106
1 files changed, 92 insertions, 14 deletions
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 05ac21662..3edd7c8a3 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -78,6 +78,9 @@ public:
gen_templates_only_ = (iter != parsed_options.end() && iter->second == "only");
+ iter = parsed_options.find("moveable_types");
+ gen_moveable_ = (iter != parsed_options.end());
+
out_dir_base_ = "gen-cpp";
}
@@ -121,7 +124,14 @@ public:
t_struct* tstruct,
bool setters = true);
void generate_copy_constructor(std::ofstream& out, t_struct* tstruct, bool is_exception);
+ void generate_move_constructor(std::ofstream& out, t_struct* tstruct, bool is_exception);
+ void generate_constructor_helper(std::ofstream& out,
+ t_struct* tstruct,
+ bool is_excpetion,
+ bool is_move);
void generate_assignment_operator(std::ofstream& out, t_struct* tstruct);
+ void generate_move_assignment_operator(std::ofstream& out, t_struct* tstruct);
+ void generate_assignment_helper(std::ofstream& out, t_struct* tstruct, bool is_move);
void generate_struct_fingerprint(std::ofstream& out, t_struct* tstruct, bool is_definition);
void generate_struct_reader(std::ofstream& out, t_struct* tstruct, bool pointers = false);
void generate_struct_writer(std::ofstream& out, t_struct* tstruct, bool pointers = false);
@@ -275,6 +285,11 @@ private:
bool gen_templates_only_;
/**
+ * True if we should generate move constructors & assignment operators.
+ */
+ bool gen_moveable_;
+
+ /**
* True iff we should use a path prefix in our #include statements for other
* thrift-generated header files.
*/
@@ -744,17 +759,53 @@ void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception)
generate_struct_writer(out, tstruct);
generate_struct_swap(f_types_impl_, tstruct);
generate_copy_constructor(f_types_impl_, tstruct, is_exception);
+ if (gen_moveable_) {
+ generate_move_constructor(f_types_impl_, tstruct, is_exception);
+ }
generate_assignment_operator(f_types_impl_, tstruct);
+ if (gen_moveable_) {
+ generate_move_assignment_operator(f_types_impl_, tstruct);
+ }
generate_struct_ostream_operator(f_types_impl_, tstruct);
}
void t_cpp_generator::generate_copy_constructor(ofstream& out,
t_struct* tstruct,
bool is_exception) {
+ generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/false);
+}
+
+void t_cpp_generator::generate_move_constructor(ofstream& out,
+ t_struct* tstruct,
+ bool is_exception) {
+ generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/true);
+}
+
+namespace {
+// Helper to convert a variable to rvalue, if move is enabled
+std::string maybeMove(std::string const& other, bool move) {
+ if (move) {
+ return "std::move(" + other + ")";
+ }
+ return other;
+}
+}
+
+void t_cpp_generator::generate_constructor_helper(ofstream& out,
+ t_struct* tstruct,
+ bool is_exception,
+ bool is_move) {
+
std::string tmp_name = tmp("other");
- indent(out) << tstruct->get_name() << "::" << tstruct->get_name() << "(const "
- << tstruct->get_name() << "& " << tmp_name << ") ";
+ indent(out) << tstruct->get_name() << "::" << tstruct->get_name();
+
+ if (is_move) {
+ out << "( " << tstruct->get_name() << "&& ";
+ } else {
+ out << "(const " << tstruct->get_name() << "& ";
+ }
+ out << tmp_name << ") ";
if (is_exception)
out << ": TException() ";
out << "{" << endl;
@@ -771,23 +822,38 @@ void t_cpp_generator::generate_copy_constructor(ofstream& out,
for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
if ((*f_iter)->get_req() != t_field::T_REQUIRED)
has_nonrequired_fields = true;
- indent(out) << (*f_iter)->get_name() << " = " << tmp_name << "." << (*f_iter)->get_name() << ";"
- << endl;
+ indent(out) << (*f_iter)->get_name() << " = "
+ << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl;
}
- if (has_nonrequired_fields)
- indent(out) << "__isset = " << tmp_name << ".__isset;" << endl;
+ if (has_nonrequired_fields) {
+ indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl;
+ }
indent_down();
indent(out) << "}" << endl;
}
void t_cpp_generator::generate_assignment_operator(ofstream& out, t_struct* tstruct) {
+ generate_assignment_helper(out, tstruct, /*is_move=*/false);
+}
+
+void t_cpp_generator::generate_move_assignment_operator(ofstream& out, t_struct* tstruct) {
+ generate_assignment_helper(out, tstruct, /*is_move=*/true);
+}
+
+void t_cpp_generator::generate_assignment_helper(ofstream& out, t_struct* tstruct, bool is_move) {
std::string tmp_name = tmp("other");
- indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::"
- "operator=(const "
- << tstruct->get_name() << "& " << tmp_name << ") {" << endl;
+ indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::operator=(";
+
+ if (is_move) {
+ out << tstruct->get_name() << "&& ";
+ } else {
+ out << "const " << tstruct->get_name() << "& ";
+ }
+ out << tmp_name << ") {" << endl;
+
indent_up();
const vector<t_field*>& members = tstruct->get_members();
@@ -801,11 +867,12 @@ void t_cpp_generator::generate_assignment_operator(ofstream& out, t_struct* tstr
for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
if ((*f_iter)->get_req() != t_field::T_REQUIRED)
has_nonrequired_fields = true;
- indent(out) << (*f_iter)->get_name() << " = " << tmp_name << "." << (*f_iter)->get_name() << ";"
- << endl;
+ indent(out) << (*f_iter)->get_name() << " = "
+ << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl;
+ }
+ if (has_nonrequired_fields) {
+ indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl;
}
- if (has_nonrequired_fields)
- indent(out) << "__isset = " << tmp_name << ".__isset;" << endl;
indent(out) << "return *this;" << endl;
indent_down();
@@ -890,10 +957,20 @@ void t_cpp_generator::generate_struct_declaration(ofstream& out,
// Copy constructor
indent(out) << tstruct->get_name() << "(const " << tstruct->get_name() << "&);" << endl;
+ // Move constructor
+ if (gen_moveable_) {
+ indent(out) << tstruct->get_name() << "(" << tstruct->get_name() << "&&);" << endl;
+ }
+
// Assignment Operator
indent(out) << tstruct->get_name() << "& operator=(const " << tstruct->get_name() << "&);"
<< endl;
+ // Move assignment operator
+ if (gen_moveable_) {
+ indent(out) << tstruct->get_name() << "& operator=(" << tstruct->get_name() << "&&);" << endl;
+ }
+
// Default constructor
indent(out) << tstruct->get_name() << "()";
@@ -4288,4 +4365,5 @@ THRIFT_REGISTER_GENERATOR(
" templates: Generate templatized reader/writer methods.\n"
" pure_enums: Generate pure enums instead of wrapper classes.\n"
" dense: Generate type specifications for the dense protocol.\n"
- " include_prefix: Use full include paths in generated files.\n")
+ " include_prefix: Use full include paths in generated files.\n"
+ " moveable_types: Generate move constructors and assignment operators.\n")