4 ms·
Is the code for this available somewhere?
by dman 11y ago
Is the code for this available somewhere?
- Kristine1975 11y agoNot at the moment, no. But it's not rocket science. The macro essentially creates a struct like this one: struct S { // How many fields are in this struct? static constexpr unsigned int FIELD_COUNT = 5; // Full specializations are not allowed inside classes, so add a dummy parameter <T> that is equivalent to S template <unsigned int Index, typename T = S> struct FieldTraits; // Partial specialization for the first field template <typename T> struct FieldTraits<0, T> { using type = int; static constexpr std::size_t OFFSET = offsetof(S, anInt); static constexpr const char* name() { return "anInt"; } static constexpr type& value(S& self) { return self.anInt; } }; // The first field itself int anInt; // Partial specialization for the second field template <typename T> struct FieldTraits<1, T> { using type = bool; static constexpr std::size_t OFFSET = offsetof(S, aBool); static constexpr const char* name() { return "aBool"; } static constexpr type& value(S& self) { return self.aBool; } }; // The second field itself bool aBool; ... }; Now that we have the meta-information about the struct's fields, we can process them: // Meta-function to process a struct's fields template <typename T, unsigned int FieldIndex, unsigned int FieldCount> struct ForEach { template <typename Functor> static void apply(T& object, Functor f) { // Get the field's value and call the functor with it auto value = T::FieldTraits<FieldIndex>::value(object); f(value); // Next field ForEach<T, FieldIndex + 1, FieldCount>::apply(object, f); }; }; // Partial specialization to end iteration template <typename T, unsigned int FieldCount> struct ForEach<T, FieldCount, FieldCount> { template <typename Functor> static void apply(T& object, Functor f) { }; }; And finally a bit of syntactic sugar: template <typename T, typename Functor> void forEachField(T& object, Functor f) { ForEach<T, 0, T::FIELD_COUNT>::apply(object, f); } *(omitted for the sake of clarity: dealing with const objects, using rvalue references and std::forward for the functor to make the code work with non-copyable functors)
- dman 11y agoThanks for taking the time to write this!