-
Hey guys, I scourged the interwebs today stealing everybody's code and put this little demo together.
The whole system is based off of C++11's std::tuple.
What started this furious rampage was me trying to get automatic serialization that could go beyond primitive types. I want to have custom encoding for custom objects. Until C++10923812093809 whatever comes out with compile-time reflection, I made this. Lemme know what you guys think (i.e. probably its complete garbage).
Link: https://github.com/tedsta/Reflectable (https://github.com/tedsta/Reflectable)
I stole code from these places so far:
http://stackoverflow.com/a/13066078 (http://stackoverflow.com/a/13066078)
http://stackoverflow.com/a/6894436 (http://stackoverflow.com/a/6894436)
Check the readme for some benchmarks. Don't know exactly what those compiler optimizations do.
-
Pythonistas, get your hands off from C++!!! :)
-
How does the final user code look? Can you show a short example? Usually, the problem with tuples is that access to them leads to non-expressive or at least cumbersome code (even with tags).
You might be interested in my project Aurora, especially the Tuple metaprogramming (http://www.bromeon.ch/libraries/aurora/v1.0/doc/_tuple_8hpp.html) file and the Named Tuple (http://www.bromeon.ch/libraries/aurora/v1.0/doc/_named_tuple_8hpp.html) macros :)
-
Pythonistas, get your hands off from C++!!! :)
Hehe it doesn't hurt performance the way python does I promise!
You might be interested in my project Aurora, especially the Tuple metaprogramming (http://www.bromeon.ch/libraries/aurora/v1.0/doc/_tuple_8hpp.html) file and the Named Tuple (http://www.bromeon.ch/libraries/aurora/v1.0/doc/_named_tuple_8hpp.html) macros :)
Your Aurora NamedTuple looks pretty cool. If you can iterate over those members (even if it's at compile time with recursive templates), then that's exactly what I want. Is that possible?
I just threw this together for fun, I don't really think it's usable yet, but maybe it could be prettied up with some macros :P Also, without the compiler optimizations, the low performance scares me.
Here's some classes:
struct Foo
{
std::string str;
int i;
};
std::ostream& operator<<(std::ostream& left, const Foo& right)
{
return left << "str: " << right.str << ", " << "i: " << right.i;
}
struct Test : public Reflectable<struct name, std::string,
struct health, int,
struct foo, Foo>
{
};
And a little sample processor to iterate through members:
class SamplePrinter
{
public:
/// \brief Int serialization
void operator () (int x)
{
std::cout << "int: " << x << std::endl;
}
/// \brief Float serialization
void operator () (float x)
{
std::cout << "float: " << x << std::endl;
}
/// \brief Double serialization
void operator () (double x)
{
std::cout << "double: " << x << std::endl;
}
/// \brief String serialization
void operator () (const std::string& x)
{
std::cout << "string: " << x << std::endl;
}
/// \brief The generic case
template <typename X>
void operator () (const X& x)
{
std::cout << "other: " << x << std::endl;
}
private:
};
And Using the stuff
Test test;
test.get<name>() = "bob";
test.get<health>() = 42;
test.get<foo>().str = "hello";
test.get<foo>().i = 24;
test.iterate(SamplePrinter());
I'm also pondering how you could make a macro to automatically set up references to the tuple members as public member variables, allowing you to access the variables with regular syntax. The benchmark shows that reference access is a little slower than regular tuple access with compiler optimizations on, though.
-
You're Aurora NamedTuple looks pretty cool. If you can iterate over those members (even if it's at compile time with recursive templates), then that's exactly what I want. Is that possible?
Sure 8)
Since every named tuple in Aurora contains a toStdTuple() member function, you can do with it anything you can do with std::tuple. That's the primary power behind it: expressive and intuitive syntax and all the nice standard tuple features.
But it's also possible to write a direct serializer. Like this, you don't have to create a temporary tuple, and you can output the member's actual names! It requires a bit of preprocessor magic, though.
#include <Aurora/Tools/NamedTuple.hpp>
#include <iostream>
#include <string>
// Preprocessor macro to output one member (the helpers are required because the
// AURORA_PP_FOREACH metafunction has a different signature
#define SERIALIZE_MEMBER_TV(Type, var) out << AURORA_PP_STRINGIZE(var) << ": " << var << "\n";
#define SERIALIZE_MEMBER_P(pair) SERIALIZE_MEMBER_TV pair
#define SERIALIZE_MEMBER(pair, index) SERIALIZE_MEMBER_P(pair)
// Preprocessor macro to output all members using iteration through typeVarPairs
#define SERIALIZER(TupleName, typeVarPairs) \
void serialize(std::ostream& out) const \
{ \
AURORA_PP_FOREACH(SERIALIZE_MEMBER, typeVarPairs) \
}
// Declare named tuple
AURORA_NAMED_TUPLE_EXT(MyTuple,
( // This is the list
(std::string, name), // of member variable
(int, health) // declarations
), //
( // This is the list of
SERIALIZER // extensions (only 1)
))
int main()
{
MyTuple tuple("monster", 42);
tuple.serialize(std::cout);
}
Output:
name: monster
health: 42
Beautiful, isn't it? :P
Have a look at the documentation (http://www.bromeon.ch/libraries/aurora/v1.0/doc/_preprocessor_8hpp.html) to learn about the involved preprocessor metafunctions. The number of arguments is currently limited to 5, but I can increase that.
-
It is pretty beautiful. Sweet. I really wish C++ supported real compile-time reflection on regular objects. Although, I know D already does :P
-
Yes, sometimes it's a pity that things are difficult to achieve natively. But at least C++ is so powerful that a lot of language features can be emulated within the language itself. The Boost libraries are extreme in this respect: Foreach, Lambda, Move, Parameter, ...
By the way, if you use this serialization in multiple places, don't hesitate to make it more user-friendly by putting all the preprocessor stuff in a header and defining a wrapper macro:
#define SERIALIZABLE_TUPLE(TupleName, typeVarPairs) \
AURORA_NAMED_TUPLE_EXT(TupleName, typeVarPairs, (SERIALIZER))