A mini reflection library for cpp, extracted and re-composed from https://github.com/clice-project/clice.
enum class Nation {
Yan,
Laterano,
Victoria,
Ursus,
Siracusa,
};
struct Info {
int rank;
int id;
};
struct Operator {
Nation nation;
int attack;
int defense;
std::string name;
Info info;
std::vector<std::string> tags;
std::unordered_map<std::string, int> other_points;
std::tuple<int, double, std::string> misc;
};
template <class T, int ident = 0, bool is_first = true>
void refl_print(const T& value) {
constexpr bool needBlank = is_first;
if constexpr(std::is_aggregate_v<T>) {
std::println("{}{{", std::string(ident, ' '));
using metainfo = refl::Struct<T>;
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
((std::print("{}{}: ", std::string(ident + 4, ' '), metainfo::fields[Is]),
refl_print<decltype(refl::st::get<T, Is>(value)), ident + 4, false>(
refl::st::get<T, Is>(value))),
...);
}(std::make_index_sequence<metainfo::member_count>{});
std::println("{}}}{}", std::string(ident, ' '), ident == 0 ? "" : ",");
return;
} else if constexpr(std::is_enum_v<T>) {
std::println("{}{},",
needBlank ? std::string(ident, ' ') : "",
refl::Enum<T>::fields[refl::impl::underlying_value(value)]);
return;
} else if constexpr(std::is_convertible_v<T, std::string_view>) {
std::println("{}\"{}\",", needBlank ? std::string(ident, ' ') : "", value);
return;
} else if constexpr(refl::rg::map_range<T>) {
std::println("{}({{", needBlank ? std::string(ident, ' ') : "");
for(const auto& [k, v]: value) {
std::print("{}{}: ", std::string(ident + 4, ' '), k);
refl_print<decltype(v), ident + 4, false>(v);
}
std::println("{}}}),", std::string(ident, ' '));
return;
} else if constexpr(refl::rg::sequence_range<T>) {
std::println("{}[", needBlank ? std::string(ident, ' ') : "");
for(const auto& v: value) {
refl_print<decltype(v), ident + 4, true>(v);
}
std::println("{}],", std::string(ident, ' '));
return;
} else {
std::println("{}{},", needBlank ? std::string(ident, ' ') : "", value);
}
};
int main(int argc, const char** argv) {
Operator op = {
.nation = Nation::Laterano,
.attack = 1500,
.defense = 800,
.name = "Exusiai",
.info =
{
.rank = 5,
.id = 1001,
},
.tags = {"DPS", "Ranged", "Physical"},
.other_points = {{"DP", 50}, {"Cost", 18}},
.misc = {42, 3.14, "Miscellaneous"},
};
refl_print(op);
return 0;
}output:
{
nation: Laterano,
attack: 1500,
defense: 800,
name: "Exusiai",
info: {
rank: 5,
id: 1001,
},
tags: [
"DPS",
"Ranged",
"Physical",
],
other_points: ({
DP: 50,
Cost: 18,
}),
misc: (42, 3.14, "Miscellaneous"),
}