-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
109 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* >= C++11 Reflection | ||
* | ||
* - Daniel Bloemendal | ||
*/ | ||
|
||
#include <tuple> | ||
#include <iostream> | ||
|
||
#include "reflection.hpp" | ||
|
||
template<typename Klass> | ||
class example_serializer { | ||
Klass& _instance; | ||
|
||
public: | ||
example_serializer(Klass& instance) : _instance(instance) {} | ||
|
||
template<typename T> | ||
void operator()(const field<Klass, T>& field) { | ||
std::cout << field.name << " (" << field.caption << "): " << (&_instance)->*field.pointer << std::endl; | ||
} | ||
|
||
void serialize() { | ||
for_each(meta<Klass>::fields(), *this); | ||
} | ||
}; | ||
|
||
class example_class { | ||
public: | ||
int integer_field; | ||
float float_field; | ||
std::string string_field; | ||
}; | ||
|
||
REFLECT_REGISTER(example_class, | ||
REFLECT_FIELD(integer_field, "an integer field"), | ||
REFLECT_FIELD(float_field, "a floating point field"), | ||
REFLECT_FIELD(string_field, "a string field")) | ||
|
||
int main() { | ||
example_class ex{1, 2.0, "hello world"}; | ||
example_serializer<example_class> s(ex); | ||
s.serialize(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* >= C++11 Reflection | ||
* | ||
* - Daniel Bloemendal | ||
*/ | ||
|
||
#pragma once | ||
|
||
struct for_each_impl { | ||
template<std::size_t I = 0, typename Function, typename... Items> | ||
inline typename std::enable_if<I == sizeof...(Items), void>::type | ||
static for_each(std::tuple<Items...>& tuple, Function& fn) {} | ||
|
||
template<std::size_t I = 0, typename Function, typename... Items> | ||
inline typename std::enable_if<I < sizeof...(Items), void>::type | ||
static for_each(std::tuple<Items...>& tuple, Function& fn) { | ||
fn(std::get<I>(tuple)); | ||
for_each<I + 1, Function, Items...>(tuple, fn); | ||
} | ||
}; | ||
|
||
template<typename Function, typename... Items> | ||
void for_each(std::tuple<Items...>& tuple, Function& fn) { | ||
for_each_impl::for_each(tuple, fn); | ||
} | ||
|
||
template<typename Function, typename... Items> | ||
void for_each(std::tuple<Items...>&& tuple, Function& fn) { | ||
for_each_impl::for_each(tuple, fn); | ||
} | ||
|
||
template<typename Klass, typename Type> | ||
struct field { | ||
// Type definitions | ||
enum { flags_constant = 1, flags_private = 2 }; | ||
typedef Type (Klass::*pointer_type); | ||
|
||
// Field information | ||
std::string name; | ||
pointer_type pointer; | ||
int flags; | ||
std::string caption; | ||
std::string doc; | ||
}; | ||
|
||
template<typename Klass, typename Type> | ||
field<Klass, Type> make_field(std::string name, Type (Klass::*pointer), int flags = 0, std::string caption = "", std::string doc = "") { | ||
return field<Klass, Type>{std::move(name), pointer, flags, std::move(caption), std::move(doc)}; | ||
} | ||
|
||
template<typename Klass> | ||
struct meta { | ||
std::tuple<> fields() { return std::tuple<>(); } | ||
}; | ||
|
||
#define REFLECT_REGISTER(cls, ...) \ | ||
template<> \ | ||
struct meta<cls> { \ | ||
typedef cls klass; \ | ||
static auto fields() -> decltype(std::make_tuple(__VA_ARGS__)) { return std::make_tuple(__VA_ARGS__); } \ | ||
}; | ||
|
||
#define REFLECT_FIELD(name, caption) \ | ||
make_field(#name, &klass::name, 0, caption, "") |