Skip to content

Instantly share code, notes, and snippets.

@nutbread
Last active March 6, 2016 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nutbread/1a3d51df81577eac2df0 to your computer and use it in GitHub Desktop.
Save nutbread/1a3d51df81577eac2df0 to your computer and use it in GitHub Desktop.
C++11 field iteration using macros and templates
#ifndef __FIELDS_H
#define __FIELDS_H
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <utility>
#include <tuple>
#include <boost/preprocessor/facilities/is_empty.hpp>
// Macro functions
// Note: if this macro is implemented without using Boost, the dependency can be removed
#define MACRO_VARARGS_IS_EMPTY(...) BOOST_PP_IS_EMPTY(__VA_ARGS__)
// Macro concat
#define FIELD_MACRO_CONCAT(a,b) FIELD_MACRO_CONCAT_INNER(a,b)
#define FIELD_MACRO_CONCAT_INNER(a,b) a ## b
// Macro recursion
#define FIELD_MACRO_EVAL(...) FIELD_MACRO_EVAL1(FIELD_MACRO_EVAL1(FIELD_MACRO_EVAL1(__VA_ARGS__)))
#define FIELD_MACRO_EVAL1(...) FIELD_MACRO_EVAL2(FIELD_MACRO_EVAL2(FIELD_MACRO_EVAL2(__VA_ARGS__)))
#define FIELD_MACRO_EVAL2(...) FIELD_MACRO_EVAL3(FIELD_MACRO_EVAL3(FIELD_MACRO_EVAL3(__VA_ARGS__)))
#define FIELD_MACRO_EVAL3(...) FIELD_MACRO_EVAL4(FIELD_MACRO_EVAL4(FIELD_MACRO_EVAL4(__VA_ARGS__)))
#define FIELD_MACRO_EVAL4(...) FIELD_MACRO_EVAL5(FIELD_MACRO_EVAL5(FIELD_MACRO_EVAL5(__VA_ARGS__)))
#define FIELD_MACRO_EVAL5(...) __VA_ARGS__
// Fields
#define FIELD_DEFER_EMPTY(...)
#define FIELD_DEFER_EXPANSION(...) __VA_ARGS__ FIELD_DEFER_EMPTY()
#define FIELD_MEMBER_DEFERRED_FN() FIELD_MEMBER
#define FIELD_MEMBER_NEXT1(...)
#define FIELD_MEMBER_NEXT0(...) FIELD_DEFER_EXPANSION(FIELD_MEMBER_DEFERRED_FN)()( __VA_ARGS__ )
#define FIELD_MEMBER(x,...) \
FIELD_MEMBER_INNER( \
FIELD_MACRO_CONCAT(FIELD_MEMBER_NEXT, MACRO_VARARGS_IS_EMPTY(__VA_ARGS__)), \
x, \
__VA_ARGS__ \
)
#define FIELD_MEMBER_INNER(next,args,...) \
FIELD_MEMBER_DECLARE args \
next( __VA_ARGS__ )
#define FIELD_MEMBER_DECLARE(x,y,...) x y;
#define FIELD_DESCRIPTOR_OFFSETOF_FN() offsetof
#define FIELD_DESCRIPTOR_DEFERRED_FN() FIELD_DESCRIPTOR
#define FIELD_DESCRIPTOR_NEXT1(...)
#define FIELD_DESCRIPTOR_NEXT0(cls,...) FIELD_DEFER_EXPANSION(FIELD_DESCRIPTOR_DEFERRED_FN)()(cls, __VA_ARGS__ )
#define FIELD_DESCRIPTOR(cls,x,...) \
FIELD_DESCRIPTOR_INNER( \
cls, \
FIELD_MACRO_CONCAT(FIELD_DESCRIPTOR_NEXT, MACRO_VARARGS_IS_EMPTY(__VA_ARGS__)), \
x, \
__VA_ARGS__ \
)
#define FIELD_DESCRIPTOR_INNER(cls,next,args,...) \
FIELD_DESCRIPTOR_DECLARE1 args \
cls \
FIELD_DESCRIPTOR_DECLARE2 args \
next(cls, __VA_ARGS__ )
#define FIELD_DESCRIPTOR_DECLARE1(x,y,...) \
struct FIELD_MACRO_CONCAT(__FieldDescriptorHiddenClass_for_,y) final { \
public: \
static ::fields::FieldNameType field_name() { return #y; } \
static constexpr const size_t field_offset() { return (FIELD_DEFER_EXPANSION(FIELD_DESCRIPTOR_OFFSETOF_FN)()(
#define FIELD_DESCRIPTOR_DECLARE2(x,y,...) \
, y)); } \
FIELD_DESCRIPTOR_DECLARE3(FIELD_MACRO_CONCAT(FIELD_DESCRIPTOR_DECLARE3_, MACRO_VARARGS_IS_EMPTY(__VA_ARGS__)), __VA_ARGS__ )\
};
#define FIELD_DESCRIPTOR_DECLARE3(fn,...) fn( __VA_ARGS__ )
#define FIELD_DESCRIPTOR_DECLARE3_1(...) \
static constexpr const ::fields::FieldFlags field_flags() { return 0; }
#define FIELD_DESCRIPTOR_DECLARE3_0(flags,...) \
static constexpr const ::fields::FieldFlags field_flags() { return flags; }
#define FIELD_TUPLE_DEFERRED_FN() FIELD_TUPLE
#define FIELD_TUPLE_NEXT1(...)
#define FIELD_TUPLE_NEXT0(...) FIELD_DEFER_EXPANSION(FIELD_TUPLE_DEFERRED_FN)()( __VA_ARGS__ )
#define FIELD_TUPLE(x,...) \
FIELD_TUPLE_INNER( \
FIELD_MACRO_CONCAT(FIELD_TUPLE_NEXT, MACRO_VARARGS_IS_EMPTY(__VA_ARGS__)), \
x, \
__VA_ARGS__ \
)
#define FIELD_TUPLE_INNER(next,args,...) \
FIELD_TUPLE_DECLARE args \
next( __VA_ARGS__ )
#define FIELD_TUPLE_DECLARE(x,y,...) \
, std::tuple< x, FIELD_MACRO_CONCAT(__FieldDescriptorHiddenClass_for_,y) >
#define FIELDS(cls,...) \
template <typename __FieldDescriptorHiddenType> friend class ::fields::FieldIteratorDescriptorGetter; \
\
FIELD_MACRO_EVAL(FIELD_MEMBER_NEXT0( __VA_ARGS__ )) \
\
FIELD_MACRO_EVAL(FIELD_DESCRIPTOR_NEXT0(cls, __VA_ARGS__ )) \
\
typedef std::tuple< cls \
FIELD_MACRO_EVAL(FIELD_TUPLE_NEXT0(__VA_ARGS__ )) \
> FieldIteratorDescriptor;
namespace fields {
typedef uint32_t FieldFlags;
typedef const char* FieldNameType;
template <typename Class, typename FieldReader>
class FieldIterator;
template <typename FieldIteratorT, size_t Index>
class FieldIteratorFunctions;
template <typename FieldIteratorT, size_t Index, bool HasFunction>
class FieldIteratorReadFunctionCaller;
template <typename Class>
class FieldIteratorClassIsTuple;
template <typename Class>
class FieldIteratorDescriptorGetter;
template <typename Type>
class Field;
template <typename FieldReader, typename Class>
inline void iterate(Class& object);
template <typename FieldReader, typename Class>
inline void iterate(Class&& object);
template <typename FieldReader, typename Class>
inline void iterate(const Class& object);
template <typename FieldReader, typename Class>
inline void iterate(Class& object, FieldReader& reader);
template <typename FieldReader, typename Class>
inline void iterate(Class&& object, FieldReader& reader);
template <typename FieldReader, typename Class>
inline void iterate(const Class& object, FieldReader& reader);
template <typename FieldReader, typename Class>
inline void iterate(Class& object, const FieldReader& reader);
template <typename FieldReader, typename Class>
inline void iterate(Class&& object, const FieldReader& reader);
template <typename FieldReader, typename Class>
inline void iterate(const Class& object, const FieldReader& reader);
template <typename FieldReader, typename Class>
inline void iterate(Class& object, FieldReader&& reader);
template <typename FieldReader, typename Class>
inline void iterate(Class&& object, FieldReader&& reader);
template <typename FieldReader, typename Class>
inline void iterate(const Class& object, FieldReader&& reader);
template <typename Class, typename FieldReader>
class FieldIterator final {
template <typename FieldIteratorT2, size_t Index2> friend class FieldIteratorFunctions;
template <typename FieldIteratorT2, size_t Index2, bool HasFunction2> friend class FieldIteratorReadFunctionCaller;
private:
typedef FieldReader FieldReaderType;
typedef typename FieldIteratorDescriptorGetter<Class>::Type FieldIteratorDescriptor;
typedef typename std::tuple_element<0, FieldIteratorDescriptor>::type ObjectType;
static constexpr const size_t FieldCount = std::tuple_size<FieldIteratorDescriptor>::value - 1;
typedef void (*Function)(FieldIterator& self);
typedef void (*ConstFunction)(FieldIterator& self);
union {
FieldReader* reader;
const FieldReader* const_reader;
} readers;
union {
ObjectType* object;
const ObjectType* const_object;
} objects;
union {
Function function;
ConstFunction const_function;
Function function_with_const_reader;
ConstFunction const_function_with_const_reader;
} functions;
FieldIterator() {}
~FieldIterator() {}
FieldIterator(FieldIterator&&) = delete;
FieldIterator(const FieldIterator&) = delete;
FieldIterator& operator = (FieldIterator&&) = delete;
FieldIterator& operator = (const FieldIterator&) = delete;
public:
static void iterate(ObjectType& object) {
FieldReader reader;
FieldIterator it;
it.readers.reader = &reader;
it.objects.object = &object;
it.functions.function = &FieldIteratorFunctions<FieldIterator, FieldCount>::function;
while (it.functions.function != nullptr) {
(it.functions.function)(it);
}
}
static void iterate(const ObjectType& object) {
FieldReader reader;
FieldIterator it;
it.readers.reader = &reader;
it.objects.const_object = &object;
it.functions.const_function = &FieldIteratorFunctions<FieldIterator, FieldCount>::const_function;
while (it.functions.const_function != nullptr) {
(it.functions.const_function)(it);
}
}
static void iterate(ObjectType& object, FieldReader& reader) {
FieldIterator it;
it.readers.reader = &reader;
it.objects.object = &object;
it.functions.function = &FieldIteratorFunctions<FieldIterator, FieldCount>::function;
while (it.functions.function != nullptr) {
(it.functions.function)(it);
}
}
static void iterate(const ObjectType& object, FieldReader& reader) {
FieldIterator it;
it.readers.reader = &reader;
it.objects.const_object = &object;
it.functions.const_function = &FieldIteratorFunctions<FieldIterator, FieldCount>::const_function;
while (it.functions.const_function != nullptr) {
(it.functions.const_function)(it);
}
}
static void iterate(ObjectType& object, const FieldReader& reader) {
FieldIterator it;
it.readers.const_reader = &reader;
it.objects.object = &object;
it.functions.function_with_const_reader = &FieldIteratorFunctions<FieldIterator, FieldCount>::function_with_const_reader;
while (it.functions.function_with_const_reader != nullptr) {
(it.functions.function_with_const_reader)(it);
}
}
static void iterate(const ObjectType& object, const FieldReader& reader) {
FieldIterator it;
it.readers.const_reader = &reader;
it.objects.const_object = &object;
it.functions.const_function_with_const_reader = &FieldIteratorFunctions<FieldIterator, FieldCount>::const_function_with_const_reader;
while (it.functions.const_function_with_const_reader != nullptr) {
(it.functions.const_function_with_const_reader)(it);
}
}
static void iterate(ObjectType& object, FieldReader&& reader) {
FieldIterator it;
it.readers.reader = &reader;
it.objects.object = &object;
it.functions.function = &FieldIteratorFunctions<FieldIterator, FieldCount>::function;
while (it.functions.function != nullptr) {
(it.functions.function)(it);
}
}
static void iterate(const ObjectType& object, FieldReader&& reader) {
FieldIterator it;
it.readers.reader = &reader;
it.objects.const_object = &object;
it.functions.const_function = &FieldIteratorFunctions<FieldIterator, FieldCount>::const_function;
while (it.functions.const_function != nullptr) {
(it.functions.const_function)(it);
}
}
};
template <typename FieldIteratorT, size_t Index>
class FieldIteratorReadFunctionCaller<FieldIteratorT, Index, false> final {
template <typename FieldIteratorT2, size_t Index2> friend class FieldIteratorFunctions;
private:
FieldIteratorReadFunctionCaller() = delete;
~FieldIteratorReadFunctionCaller() = delete;
FieldIteratorReadFunctionCaller(FieldIteratorReadFunctionCaller&&) = delete;
FieldIteratorReadFunctionCaller(const FieldIteratorReadFunctionCaller&) = delete;
FieldIteratorReadFunctionCaller& operator = (FieldIteratorReadFunctionCaller&&) = delete;
FieldIteratorReadFunctionCaller& operator = (const FieldIteratorReadFunctionCaller&) = delete;
static inline void read_field(FieldIteratorT&) {}
static inline void read_const_field(FieldIteratorT&) {}
static inline void read_field_with_const_reader(FieldIteratorT&) {}
static inline void read_const_field_with_const_reader(FieldIteratorT&) {}
};
template <typename FieldIteratorT, size_t Index>
class FieldIteratorReadFunctionCaller<FieldIteratorT, Index, true> final {
template <typename FieldIteratorT2, size_t Index2> friend class FieldIteratorFunctions;
private:
typedef typename FieldIteratorT::ObjectType ObjectType;
typedef typename FieldIteratorT::FieldIteratorDescriptor Descriptor;
typedef typename std::tuple_element<std::tuple_size<Descriptor>::value - Index, Descriptor>::type FieldTuple;
typedef typename std::tuple_element<0, FieldTuple>::type FieldType;
typedef typename std::tuple_element<1, FieldTuple>::type FieldDescriptor;
FieldIteratorReadFunctionCaller() = delete;
~FieldIteratorReadFunctionCaller() = delete;
FieldIteratorReadFunctionCaller(FieldIteratorReadFunctionCaller&&) = delete;
FieldIteratorReadFunctionCaller(const FieldIteratorReadFunctionCaller&) = delete;
FieldIteratorReadFunctionCaller& operator = (FieldIteratorReadFunctionCaller&&) = delete;
FieldIteratorReadFunctionCaller& operator = (const FieldIteratorReadFunctionCaller&) = delete;
static inline FieldType* get_value(ObjectType* object) {
return static_cast<FieldType*>(
static_cast<void*>(
static_cast<char*>(static_cast<void*>(object)) +
FieldDescriptor::field_offset()
)
);
}
static inline void read_field(FieldIteratorT& it) {
Field<FieldType> field(
FieldDescriptor::field_name(),
FieldDescriptor::field_flags(),
*get_value(it.objects.object)
);
it.readers.reader->read(field);
}
static inline void read_const_field(FieldIteratorT& it) {
Field<FieldType> field(
FieldDescriptor::field_name(),
FieldDescriptor::field_flags(),
*get_value(const_cast<ObjectType*>(it.objects.const_object))
);
it.readers.reader->read(static_cast<const Field<FieldType>&>(field));
}
static inline void read_field_with_const_reader(FieldIteratorT& it) {
Field<FieldType> field(
FieldDescriptor::field_name(),
FieldDescriptor::field_flags(),
*get_value(it.objects.object)
);
it.readers.const_reader->read(field);
}
static inline void read_const_field_with_const_reader(FieldIteratorT& it) {
Field<FieldType> field(
FieldDescriptor::field_name(),
FieldDescriptor::field_flags(),
*get_value(const_cast<ObjectType*>(it.objects.const_object))
);
it.readers.const_reader->read(static_cast<const Field<FieldType>&>(field));
}
};
template <typename FieldIteratorT, size_t Index>
class FieldIteratorFunctions final {
template <typename Class2, typename FieldReader2> friend class FieldIterator;
template <typename FieldIteratorT2, size_t Index2> friend class FieldIteratorFunctions;
private:
typedef typename FieldIteratorT::FieldReaderType FieldReaderType;
typedef typename FieldIteratorT::FieldIteratorDescriptor Descriptor;
typedef typename std::tuple_element<std::tuple_size<Descriptor>::value - Index, Descriptor>::type FieldTuple;
typedef typename std::tuple_element<0, FieldTuple>::type FieldType;
FieldIteratorFunctions() = delete;
~FieldIteratorFunctions() = delete;
FieldIteratorFunctions(FieldIteratorFunctions&&) = delete;
FieldIteratorFunctions(const FieldIteratorFunctions&) = delete;
FieldIteratorFunctions& operator = (FieldIteratorFunctions&&) = delete;
FieldIteratorFunctions& operator = (const FieldIteratorFunctions&) = delete;
// has_reader_function is used to detect if a correct read(...) function is available
// if the function is not available, no read(...) function is called
template <typename T, typename U>
static constexpr auto has_reader_function(T t, U u) -> std::is_same<
decltype(t->read(*u)),
decltype(t->read(*u))
>;
template <typename T, typename U>
static constexpr auto has_reader_function(...) -> std::false_type;
static void function(FieldIteratorT& it) {
typedef decltype(has_reader_function<FieldReaderType*, Field<FieldType>*>(0, 0)) HasReaderFunction;
FieldIteratorReadFunctionCaller<FieldIteratorT, Index, HasReaderFunction::value>::read_field(it);
it.functions.function = &FieldIteratorFunctions<FieldIteratorT, Index - 1>::function;
}
static void const_function(FieldIteratorT& it) {
typedef decltype(has_reader_function<FieldReaderType*, const Field<FieldType>*>(0, 0)) HasReaderFunction;
FieldIteratorReadFunctionCaller<FieldIteratorT, Index, HasReaderFunction::value>::read_const_field(it);
it.functions.const_function = &FieldIteratorFunctions<FieldIteratorT, Index - 1>::const_function;
}
static void function_with_const_reader(FieldIteratorT& it) {
typedef decltype(has_reader_function<const FieldReaderType*, Field<FieldType>*>(0, 0)) HasReaderFunction;
FieldIteratorReadFunctionCaller<FieldIteratorT, Index, HasReaderFunction::value>::read_field_with_const_reader(it);
it.functions.function_with_const_reader = &FieldIteratorFunctions<FieldIteratorT, Index - 1>::function_with_const_reader;
}
static void const_function_with_const_reader(FieldIteratorT& it) {
typedef decltype(has_reader_function<const FieldReaderType*, const Field<FieldType>*>(0, 0)) HasReaderFunction;
FieldIteratorReadFunctionCaller<FieldIteratorT, Index, HasReaderFunction::value>::read_const_field_with_const_reader(it);
it.functions.const_function_with_const_reader = &FieldIteratorFunctions<FieldIteratorT, Index - 1>::const_function_with_const_reader;
}
};
template <typename FieldIteratorT>
class FieldIteratorFunctions<FieldIteratorT, 0> final {
template <typename Class2, typename FieldReader2> friend class FieldIterator;
template <typename FieldIteratorT2, size_t Index2> friend class FieldIteratorFunctions;
private:
FieldIteratorFunctions() = delete;
~FieldIteratorFunctions() = delete;
FieldIteratorFunctions(FieldIteratorFunctions&&) = delete;
FieldIteratorFunctions(const FieldIteratorFunctions&) = delete;
FieldIteratorFunctions& operator = (FieldIteratorFunctions&&) = delete;
FieldIteratorFunctions& operator = (const FieldIteratorFunctions&) = delete;
static void function(FieldIteratorT& it) {
it.functions.function = nullptr;
}
static void const_function(FieldIteratorT& it) {
it.functions.const_function = nullptr;
}
static void function_with_const_reader(FieldIteratorT& it) {
it.functions.function_with_const_reader = nullptr;
}
static void const_function_with_const_reader(FieldIteratorT& it) {
it.functions.const_function_with_const_reader = nullptr;
}
};
template <typename Class>
class FieldIteratorClassIsTuple final : private std::true_type {
template <typename Class2> friend class FieldIteratorDescriptorGetter;
private:
FieldIteratorClassIsTuple() = delete;
~FieldIteratorClassIsTuple() = delete;
FieldIteratorClassIsTuple(FieldIteratorClassIsTuple&&) = delete;
FieldIteratorClassIsTuple(const FieldIteratorClassIsTuple&) = delete;
FieldIteratorClassIsTuple& operator = (FieldIteratorClassIsTuple&&) = delete;
FieldIteratorClassIsTuple& operator = (const FieldIteratorClassIsTuple&) = delete;
};
template <typename... Args>
class FieldIteratorClassIsTuple<std::tuple<Args...> > final : private std::false_type {
template <typename Class2> friend class FieldIteratorDescriptorGetter;
private:
FieldIteratorClassIsTuple() = delete;
~FieldIteratorClassIsTuple() = delete;
FieldIteratorClassIsTuple(FieldIteratorClassIsTuple&&) = delete;
FieldIteratorClassIsTuple(const FieldIteratorClassIsTuple&) = delete;
FieldIteratorClassIsTuple& operator = (FieldIteratorClassIsTuple&&) = delete;
FieldIteratorClassIsTuple& operator = (const FieldIteratorClassIsTuple&) = delete;
};
template <typename Class>
class FieldIteratorDescriptorGetter final {
template <typename Type2, typename DataType2> friend class FieldIterator;
private:
FieldIteratorDescriptorGetter() = delete;
~FieldIteratorDescriptorGetter() = delete;
FieldIteratorDescriptorGetter(FieldIteratorDescriptorGetter&&) = delete;
FieldIteratorDescriptorGetter(const FieldIteratorDescriptorGetter&) = delete;
FieldIteratorDescriptorGetter& operator = (FieldIteratorDescriptorGetter&&) = delete;
FieldIteratorDescriptorGetter& operator = (const FieldIteratorDescriptorGetter&) = delete;
typedef std::tuple<Class> DefaultType;
template <typename T>
static constexpr auto test(T*) -> typename std::conditional<
FieldIteratorClassIsTuple<typename T::FieldIteratorDescriptor>::value,
DefaultType,
typename T::FieldIteratorDescriptor
>::type;
template <typename T>
static constexpr auto test(...) -> DefaultType;
typedef decltype(test<Class>(0)) Type;
};
template <typename Type2>
class Field final {
template <typename FieldIteratorT2, size_t Index2, bool HasFunction2> friend class FieldIteratorReadFunctionCaller;
public:
typedef Type2 Type;
private:
const FieldNameType name;
const FieldFlags flags;
Type& value;
Field() = delete;
~Field() {}
Field(Field&&) = delete;
Field(const Field&) = delete;
Field& operator = (Field&&) = delete;
Field& operator = (const Field&) = delete;
Field(
FieldNameType name,
FieldFlags flags,
Type& value
) :
name(name),
flags(flags),
value(value)
{
}
public:
FieldNameType get_name() const { return this->name; }
FieldFlags get_flags() const { return this->flags; }
Type& get_value() { return this->value; }
const Type& get_value() const { return this->value; }
};
template <typename FieldReader, typename Class>
inline void iterate(Class& object) {
FieldIterator<Class, FieldReader>::iterate(object);
}
template <typename FieldReader, typename Class>
inline void iterate(Class&& object) {
FieldIterator<Class, FieldReader>::iterate(object);
}
template <typename FieldReader, typename Class>
inline void iterate(const Class& object) {
FieldIterator<Class, FieldReader>::iterate(object);
}
template <typename FieldReader, typename Class>
inline void iterate(Class& object, FieldReader& reader) {
FieldIterator<Class, FieldReader>::iterate(object, reader);
}
template <typename FieldReader, typename Class>
inline void iterate(Class&& object, FieldReader& reader) {
FieldIterator<Class, FieldReader>::iterate(object, reader);
}
template <typename FieldReader, typename Class>
inline void iterate(const Class& object, FieldReader& reader) {
FieldIterator<Class, FieldReader>::iterate(object, reader);
}
template <typename FieldReader, typename Class>
inline void iterate(Class& object, const FieldReader& reader) {
FieldIterator<Class, FieldReader>::iterate(object, reader);
}
template <typename FieldReader, typename Class>
inline void iterate(Class&& object, const FieldReader& reader) {
FieldIterator<Class, FieldReader>::iterate(object, reader);
}
template <typename FieldReader, typename Class>
inline void iterate(const Class& object, const FieldReader& reader) {
FieldIterator<Class, FieldReader>::iterate(object, reader);
}
template <typename FieldReader, typename Class>
inline void iterate(Class& object, FieldReader&& reader) {
FieldIterator<Class, FieldReader>::iterate(object, std::forward<FieldReader>(reader));
}
template <typename FieldReader, typename Class>
inline void iterate(Class&& object, FieldReader&& reader) {
FieldIterator<Class, FieldReader>::iterate(object, std::forward<FieldReader>(reader));
}
template <typename FieldReader, typename Class>
inline void iterate(const Class& object, FieldReader&& reader) {
FieldIterator<Class, FieldReader>::iterate(object, std::forward<FieldReader>(reader));
}
} // namespace fields
#endif // __FIELDS_H
#include "Fields.hpp"
#include <string>
#include <iostream>
class Test final {
private:
FIELDS(
Test,
(int, x),
(float, y, 1),
(double, z, 2),
(const char*, w, 3)
)
bool visible;
public:
Test() :
x(1),
y(2.5f),
z(3.75),
w("test"),
visible(false)
{}
};
struct FieldReader final {
template <typename Type>
void read(fields::Field<Type>& field) {
std::cout << field.get_name() << "=" << field.get_value() << " (" << field.get_flags() << ")" << std::endl;
}
void read(fields::Field<int>& field) {
std::cout << field.get_name() << "=" << field.get_value() << " (" << field.get_flags() << ") [non-template-function-call]" << std::endl;
}
};
int main(int, char**) {
Test test;
fields::iterate(test, FieldReader());
return 0;
}
/*
cls && g++ -Wall -std=c++11 -o FieldsTest.exe -I. FieldsTest.cpp && FieldsTest.exe
"%VS140COMNTOOLS%\..\..\VC\bin\vcvars32.bat"
cls && cl /nologo /EHsc /W4 FieldsTest.cpp /Fe:FieldsTest.cl.exe /I. && FieldsTest.cl.exe
*/
#include "Fields.hpp"
#include <string>
#include <iostream>
#include <typeinfo>
#ifdef __GNUC__
#include <cxxabi.h>
#endif
template <typename Type>
std::string get_type_name() {
std::string s;
const char* name = typeid(Type).name();
#ifdef __GNUC__
int status;
char* true_name = abi::__cxa_demangle(name, nullptr, nullptr, &status);
s = (status == 0 ? true_name : name);
free(true_name);
#else
s = name;
#endif
return s;
}
class Test final {
private:
FIELDS(
Test,
(int, x),
(float, y, 1),
(double, z, 2),
(const char*, w, 3)
)
bool visible;
public:
Test() :
x(1),
y(2.5f),
z(3.75),
w("test"),
visible(false)
{}
};
class TestNoFields final {};
class FieldReader final {
public:
int value;
FieldReader() : value(0) {}
template <typename Type>
void read(fields::Field<Type>& field) {
++this->value;
std::cout << " v1: " << get_type_name<Type>() << " " << field.get_name() << "=" << field.get_value() << " (" << field.get_flags() << ")" << std::endl;
}
template <typename Type>
void read(fields::Field<Type>& field) const {
std::cout << " v2: " << get_type_name<Type>() << " " << field.get_name() << "=" << field.get_value() << " (" << field.get_flags() << ")" << std::endl;
}
template <typename Type>
void read(const fields::Field<Type>& field) {
++this->value;
std::cout << " v3: " << get_type_name<Type>() << " " << field.get_name() << "=" << field.get_value() << " (" << field.get_flags() << ")" << std::endl;
}
template <typename Type>
void read(const fields::Field<Type>& field) const {
std::cout << " v4: " << get_type_name<Type>() << " " << field.get_name() << "=" << field.get_value() << " (" << field.get_flags() << ")" << std::endl;
}
};
class FieldReaderStatic final {
public:
template <typename Type>
static void read(fields::Field<Type>& field) {
std::cout << " v5: " << get_type_name<Type>() << " " << field.get_name() << "=" << field.get_value() << " (" << field.get_flags() << ")" << std::endl;
}
template <typename Type>
static void read(const fields::Field<Type>& field) {
std::cout << " v6: " << get_type_name<Type>() << " " << field.get_name() << "=" << field.get_value() << " (" << field.get_flags() << ")" << std::endl;
}
};
int main(int, char**) {
Test test;
TestNoFields test2;
FieldReader reader;
std::cout << "temp object, no reader" << std::endl;
fields::iterate<FieldReader>(Test());
std::cout << std::endl << "temp object, temp reader" << std::endl;
fields::iterate(Test(), FieldReader());
std::cout << std::endl << "temp object, non-const reader" << std::endl;
fields::iterate(Test(), reader);
std::cout << std::endl << "temp object, const reader" << std::endl;
fields::iterate(Test(), static_cast<const FieldReader&>(reader));
std::cout << std::endl;
std::cout << std::endl << "non-const object, no reader" << std::endl;
fields::iterate<FieldReader>(test);
std::cout << std::endl << "non-const object, temp reader" << std::endl;
fields::iterate(test, FieldReader());
std::cout << std::endl << "non-const object, non-const reader" << std::endl;
fields::iterate(test, reader);
std::cout << std::endl << "non-const object, const reader" << std::endl;
fields::iterate(test, static_cast<const FieldReader&>(reader));
std::cout << std::endl;
std::cout << std::endl << "const object, no reader" << std::endl;
fields::iterate<FieldReader>(static_cast<const Test&>(test));
std::cout << std::endl << "const object, temp reader" << std::endl;
fields::iterate(static_cast<const Test&>(test), FieldReader());
std::cout << std::endl << "const object, non-const reader" << std::endl;
fields::iterate(static_cast<const Test&>(test), reader);
std::cout << std::endl << "const object, const reader" << std::endl;
fields::iterate(static_cast<const Test&>(test), static_cast<const FieldReader&>(reader));
std::cout << std::endl;
std::cout << std::endl << "non-const object, static reader" << std::endl;
fields::iterate<FieldReaderStatic>(test);
std::cout << std::endl << "const object, static reader" << std::endl;
fields::iterate<FieldReaderStatic>(static_cast<const Test&>(test));
std::cout << std::endl;
std::cout << std::endl << "non-const object (no fields), no reader" << std::endl;
fields::iterate<FieldReader>(test2);
std::cout << std::endl;
std::cout << std::endl << "reader.value=" << reader.value << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment