in compiler/cpp/src/thrift/generate/t_cpp_generator.cc [1210:1425]
void t_cpp_generator::generate_struct_declaration(ostream& out,
t_struct* tstruct,
bool is_exception,
bool pointers,
bool read,
bool write,
bool swap,
bool is_user_struct) {
string extends = "";
if (is_exception) {
extends = " : public ::apache::thrift::TException";
} else {
if (is_user_struct && !gen_templates_) {
extends = " : public virtual ::apache::thrift::TBase";
}
}
// Get members
vector<t_field*>::const_iterator m_iter;
const vector<t_field*>& members = tstruct->get_members();
// Write the isset structure declaration outside the class. This makes
// the generated code amenable to processing by SWIG.
// We only declare the struct if it gets used in the class.
// Isset struct has boolean fields, but only for non-required fields.
bool has_nonrequired_fields = false;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if ((*m_iter)->get_req() != t_field::T_REQUIRED)
has_nonrequired_fields = true;
}
if (has_nonrequired_fields && (!pointers || read)) {
out << indent() << "typedef struct _" << tstruct->get_name() << "__isset {" << '\n';
indent_up();
indent(out) << "_" << tstruct->get_name() << "__isset() ";
bool first = true;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
continue;
}
string isSet = ((*m_iter)->get_value() != nullptr) ? "true" : "false";
if (first) {
first = false;
out << ": " << (*m_iter)->get_name() << "(" << isSet << ")";
} else {
out << ", " << (*m_iter)->get_name() << "(" << isSet << ")";
}
}
out << " {}" << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
indent(out) << "bool " << (*m_iter)->get_name() << " :1;" << '\n';
}
}
indent_down();
indent(out) << "} _" << tstruct->get_name() << "__isset;" << '\n';
}
out << '\n';
generate_java_doc(out, tstruct);
// Open struct def
out << indent() << "class " << tstruct->get_name() << extends << " {" << '\n' << indent()
<< " public:" << '\n' << '\n';
indent_up();
if (!gen_no_constructors_ && !pointers) {
bool ok_noexcept = is_struct_storage_not_throwing(tstruct);
// Copy constructor
indent(out) << tstruct->get_name() << "(const " << tstruct->get_name() << "&)"
<< (ok_noexcept? " noexcept" : "") << ';' << '\n';
// Move constructor
if (gen_moveable_) {
indent(out) << tstruct->get_name() << "(" << tstruct->get_name() << "&&) noexcept;"
<< '\n';
}
// Assignment Operator
indent(out) << tstruct->get_name() << "& operator=(const " << tstruct->get_name() << "&)"
<< (ok_noexcept? " noexcept" : "") << ';' << '\n';
// Move assignment operator
if (gen_moveable_) {
indent(out) << tstruct->get_name() << "& operator=(" << tstruct->get_name() << "&&) noexcept;"
<< '\n';
}
bool has_default_value = has_field_with_default_value(tstruct);
// Default constructor
std::string clsname_ctor = tstruct->get_name() + "()";
indent(out) << clsname_ctor << (has_default_value ? "" : " noexcept") << ";" << '\n';
}
if (!gen_no_constructors_ && tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
out << '\n' << indent();
if (!gen_templates_) out << "virtual ";
out << "~" << tstruct->get_name() << "() noexcept;\n";
}
// Declare all fields
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
generate_java_doc(out, *m_iter);
indent(out) << declare_field(*m_iter,
!pointers && gen_no_constructors_,
(pointers && !(*m_iter)->get_type()->is_xception()),
!read) << '\n';
}
// Add the __isset data member if we need it, using the definition from above
if (has_nonrequired_fields && (!pointers || read)) {
out << '\n' << indent() << "_" << tstruct->get_name() << "__isset __isset;" << '\n';
}
// Create a setter function for each field
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if (pointers) {
continue;
}
if (is_reference((*m_iter))) {
out << '\n' << indent() << "void __set_" << (*m_iter)->get_name() << "(::std::shared_ptr<"
<< type_name((*m_iter)->get_type(), false, false) << ">";
out << " val);" << '\n';
} else {
out << '\n' << indent() << "void __set_" << (*m_iter)->get_name() << "("
<< type_name((*m_iter)->get_type(), false, true);
out << " val);" << '\n';
}
}
out << '\n';
if (!pointers) {
// Should we generate default operators?
if (!gen_no_default_operators_) {
// Generate an equality testing operator.
out << indent() << "bool operator == (const " << tstruct->get_name() << " & "
<< (members.size() > 0 ? "rhs" : "/* rhs */") << ") const;" << '\n';
out << indent() << "bool operator != (const " << tstruct->get_name() << " &rhs) const {"
<< '\n' << indent() << " return !(*this == rhs);" << '\n' << indent() << "}" << '\n'
<< '\n';
// Generate the declaration of a less-than operator. This must be
// implemented by the application developer if they wish to use it. (They
// will get a link error if they try to use it without an implementation.)
out << indent() << "bool operator < (const " << tstruct->get_name() << " & ) const;" << '\n'
<< '\n';
}
}
if (read) {
if (gen_templates_) {
out << indent() << "template <class Protocol_>" << '\n' << indent()
<< "uint32_t read(Protocol_* iprot);" << '\n';
} else {
out << indent() << "uint32_t read("
<< "::apache::thrift::protocol::TProtocol* iprot)";
if(!is_exception && !extends.empty())
out << " override";
out << ';' << '\n';
}
}
if (write) {
if (gen_templates_) {
out << indent() << "template <class Protocol_>" << '\n' << indent()
<< "uint32_t write(Protocol_* oprot) const;" << '\n';
} else {
out << indent() << "uint32_t write("
<< "::apache::thrift::protocol::TProtocol* oprot) const";
if(!is_exception && !extends.empty())
out << " override";
out << ';' << '\n';
}
}
out << '\n';
if (is_user_struct && !has_custom_ostream(tstruct)) {
out << indent();
if (!gen_templates_) out << "virtual ";
generate_struct_print_method_decl(out, nullptr);
out << ";" << '\n';
}
// std::exception::what()
if (is_exception) {
out << indent() << "mutable std::string thriftTExceptionMessageHolder_;" << '\n';
out << indent();
generate_exception_what_method_decl(out, tstruct, false);
out << ";" << '\n';
}
indent_down();
indent(out) << "};" << '\n' << '\n';
if (swap) {
// Generate a namespace-scope swap() function
if (tstruct->get_name() == "a" || tstruct->get_name() == "b") {
out << indent() << "void swap(" << tstruct->get_name() << " &a1, " << tstruct->get_name()
<< " &a2);" << '\n' << '\n';
} else {
out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name()
<< " &b);" << '\n' << '\n';
}
}
if (is_user_struct) {
generate_struct_ostream_operator_decl(out, tstruct);
}
}