Skip to content

Instantly share code, notes, and snippets.

@dolinenkov
Last active August 2, 2019 11:54
Show Gist options
  • Select an option

  • Save dolinenkov/ad7bef14abe56e59e3b9672cd69a6818 to your computer and use it in GitHub Desktop.

Select an option

Save dolinenkov/ad7bef14abe56e59e3b9672cd69a6818 to your computer and use it in GitHub Desktop.
#include <tuple>
#include <string>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
namespace class_info {
struct String {
const char * s;
};
template<class Object, class Member>
using Attribute = Member(Object::*);
template<class Object, class Result, class... Arguments>
using Method = Result(Object::*)(Arguments...);
template<class Object, class Member>
struct AttributeInfo {
String name;
Attribute<Object, Member> attribute;
};
template<class Object, class Member>
constexpr auto attribute(const char * name, Attribute<Object, Member> attribute) {
return AttributeInfo<Object, Member>{name, attribute};
}
template<class T>
constexpr auto getAttributeList(T &&) {
return std::make_tuple();
}
template<size_t Index, class AttributeList>
constexpr auto getAttribute(AttributeList attributeList) {
return std::get<Index>(attributeList);
}
//
template<size_t Index, size_t MaxIndex, class Visitor, class Tuple>
void visitImpl(Visitor v, Tuple & t) {
if constexpr (Index < MaxIndex) {
v(std::get<Index>(t));
visitImpl<Index + 1, MaxIndex, Visitor, Tuple>(v, t);
}
}
template<class Visitor, class Tuple>
void visit(Visitor v, Tuple & t) {
visitImpl<0, std::tuple_size<Tuple>::value, Visitor, Tuple>(v, t);
}
//
}
struct MyStruct {
int a;
float b;
std::string c;
};
template<>
constexpr auto class_info::getAttributeList<MyStruct>(MyStruct &&) {
return std::make_tuple(
attribute("a", &MyStruct::a),
attribute("b", &MyStruct::b),
attribute("c", &MyStruct::c)
);
}
template<class Target>
struct CMapReader {
Target & target;
std::map<std::string, std::string> kvmap;
template<class Attribute>
void operator()(Attribute & attribute) {
auto it = kvmap.find(attribute.name.s);
if (it != kvmap.end()) {
std::istringstream ss(it->second);
ss >> (target.*(attribute.attribute));
}
}
};
template<class O>
struct COutVisitor
{
O & o;
template<class T>
void operator()(T t) {
std::cout
<< t.name.s
<< '\t'
<< o.*(t.attribute)
<< std::endl;
}
};
int main(int argc, char * argv[]) {
MyStruct myStruct;
myStruct.a = -42;
myStruct.b = 100.500;
myStruct.c = "testing universal member traversing";
auto d = class_info::getAttributeList(static_cast<MyStruct &&>(myStruct));
class_info::visit(COutVisitor<MyStruct>{myStruct}, d);
const std::map<std::string, std::string> kvmap =
{
{"a", "-42"},
{"b", "0.5"},
{"c", "test"}
};
MyStruct readable;
auto reader = CMapReader<MyStruct>{readable, kvmap};
class_info::visit(reader, d);
auto sm0 = class_info::getAttribute<0>(d);
auto sm1 = class_info::getAttribute<1>(d);
auto sm2 = class_info::getAttribute<2>(d);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment