in cppwinrt/code_writers.h [2669:2786]
static bool write_structs(writer& w, std::vector<TypeDef> const& types)
{
auto format = R"( struct %
{
% };
inline bool operator==(% const& left, % const& right)%
{
return%;
}
inline bool operator!=(% const& left, % const& right)%
{
return !(left == right);
}
)";
if (types.empty())
{
return false;
}
struct complex_struct
{
complex_struct(writer& w, TypeDef const& type) :
type(type),
is_noexcept(!has_reference(type))
{
for (auto&& field : type.FieldList())
{
fields.emplace_back(field.Name(), w.write_temp("%", field.Signature().Type()));
}
}
static bool has_reference(TypeDef const&)
{
return false;
};
TypeDef type;
std::vector<std::pair<std::string_view, std::string>> fields;
bool is_noexcept{ false };
};
std::vector<complex_struct> structs;
structs.reserve(types.size());
for (auto&& type : types)
{
structs.emplace_back(w, type);
}
auto depends = [](writer& w, complex_struct const& left, complex_struct const& right)
{
auto right_type = w.write_temp("%", right.type);
std::string right_as_ref = std::string("winrt::Windows::Foundation::IReference<") + right_type + ">";
for (auto&& field : left.fields)
{
if (right_type == field.second || right_as_ref == field.second)
{
return true;
}
}
return false;
};
for (size_t left = 0; left < structs.size(); ++left)
{
for (size_t right = left + 1; right < structs.size(); ++right)
{
if (depends(w, structs[left], structs[right]))
{
// Left depends on right, therefore move right in front of left.
complex_struct temp = std::move(structs[right]);
structs.erase(structs.begin() + right);
structs.insert(structs.begin() + left, std::move(temp));
// Start over from the newly inserted struct.
right = structs.size();
--left;
}
}
}
bool promote = false;
auto cpp_namespace = w.write_temp("@", w.type_namespace);
for (auto&& type : structs)
{
auto name = type.type.TypeName();
std::string_view is_noexcept = type.is_noexcept ? " noexcept" : "";
w.write(format,
name,
bind_each<write_struct_field>(type.fields),
name,
name,
is_noexcept,
bind<write_struct_equality>(type.fields),
name,
name,
is_noexcept);
for (auto&& field : type.fields)
{
if (field.second.find(':') == std::string::npos)
{
continue;
}
if (!starts_with(field.second, cpp_namespace))
{
promote = true;
}
}
}
return promote;
}