4 ms·
Any sort of reflection brings C++ one step closer to Python. Implementing serialization for complex types often requires manual code writing or external tools.
by greenavocado 2y ago
Any sort of reflection brings C++ one step closer to Python.
Implementing serialization for complex types often requires manual code writing or external tools. With static reflection you could automate this process
template<typename T>
void serialize(const T& obj, std::ostream& os) {
for_each(reflect(T), [&](auto member) {
os << member.name() << ": " << member.get(obj) << "\n";
});
}
Simplified property systems
class Person {
public:
Person(const std::string& name, int age)
: name(name), age(age) {}
std::string getName() const { return name; }
void setName(const std::string& name) { this->name = name; }
int getAge() const { return age; }
void setAge(int age) { this->age = age; }
private:
std::string name;
int age;
REFLECT_PROPERTIES(
(name, "Name of the person"),
(age, "Age of the person")
)
};
int main() {
Person person("Alice", 30);
auto properties = reflect::getProperties<Person>();
for (const auto& prop : properties) {
std::cout << "Property: " << prop.name
<< " (" << prop.description << ")" << std::endl;
auto value = reflect::get(person, prop.name);
std::cout << "Value: " << value << std::endl;
if (prop.name == "age") {
reflect::set(person, prop.name, 31);
}
}
std::cout << "Updated age: " << person.getAge() << std::endl;
return 0;
}
Simplified template metaprogramming
template<typename T>
void printTypeInfo() {
constexpr auto info = reflect(T);
std::cout << "Type name: " << info.name() << "\n";
std::cout << "Member count: " << info.members().size() << "\n";
}
Easier to write generic algorithms that work with arbitrary types
template<typename T>
void printAllMembers(const T& obj) {
for_each(reflect(T), [&](auto member) {
std::cout << member.name() << ": " << member.get(obj) << "\n";
});
}
- tsimionescu 2y agoNote that you should really be using std:print rather than std::cout if using modern C++.
- npoc 2y agoJust because it's newer doesn't make it better. There are good reasons for avoiding iostream
- tsimionescu 2y agoThat's my point - iostream is a really bad piece of code, and if you're anyway going to use modern C++, it's really recommended to stop using it.
- npoc 2y agoSorry, I got your comment completely backwards
- pjmlp 2y agoiostream is good enough for most jobs, unless one is writing high performace IO code battling for each ms.
- tsimionescu 2y agoOr unless one wants to write formatted output, or unless one wants to handle IO errors with RAII...
- pjmlp 2y agoPerfectly fine with existing operators and handle classes. Happily using iostreams since Turbo C++ 1.0 for MS-DOS in 1993, and will keep doing so, unless chasing ms optimizations.
- spacechild1 2y ago> There are good reasons for avoiding iostream I guess that's not what you wanted to say, but I fully agree :)
- greenavocado 2y agoFair enough. Serialization #include <print> template<typename T> void serialize(const T& obj, std::ostream& os) { for_each(reflect(T), [&](auto member) { std::print("{}: {}\n", member.name(), member.get(obj)); }); } Simplified property systems class Person { public: Person(const std::string& name, int age) : name(name), age(age) {} std::string getName() const { return name; } void setName(const std::string& name) { this->name = name; } int getAge() const { return age; } void setAge(int age) { this->age = age; } private: std::string name; int age; REFLECT_PROPERTIES( (name, "Name of the person"), (age, "Age of the person") ) }; int main() { Person person("Alice", 30); auto properties = reflect::getProperties<Person>(); for (const auto& prop : properties) { std::print("Property: {} ({})\n", prop.name, prop.description); auto value = reflect::get(person, prop.name); std::print("Value: {}\n", value); if (prop.name == "age") { reflect::set(person, prop.name, 31); } } std::print("Updated age: {}\n", person.getAge()); return 0; } Simplified template metaprogramming template<typename T> void printTypeInfo() { constexpr auto info = reflect(T); std::print("Type name: {}\n", info.name()); std::print("Member count: {}\n", info.members().size()); } Generic algorithm for printing all members template<typename T> void printAllMembers(const T& obj) { for_each(reflect(T), [&](auto member) { std::print("{}: {}\n", member.name(), member.get(obj)); }); }