In my previous post I gave examples on how to iterate over a tuple via recursive instantiations. It became a bit of an annoyance to keep doing this, so I played around until I found something better. Assuming library code exists somewhere that looks a little like so:
namespace tupleExt { template <typename F> struct With { template <std::size_t N = 0, typename... Args, typename... FArgs> static inline typename std::enable_if<N == sizeof...(Args), void>::type iterate(const std::tuple<Args...>& t, FArgs&...){ } template <std::size_t N = 0, typename... Args, typename... FArgs> static inline typename std::enable_if<N < sizeof...(Args), void>::type iterate(const std::tuple<Args...>& t, FArgs&... fargs){ F::evaluate( std::get<N>(t), fargs... ); iterate<N+1, Args...>(t, fargs...); } }; }
Each iterator then needs to just look like so:
struct Set { template <typename T, typename S> static void evaluate( const Field_<T, S>& field, Json::Value& jv, T& t){ jv[field.name] = t.*(field.field); } }; template <typename T> static Json::Value& operator<<(Json::Value& jv, T& t) { tupleExt::With<Set>::iterate( MetaClass_<T>::fields(), jv, t); return jv; }
It's the same basic mechanism, except generalized out some. I like this approach for a few reasons. First, every template type that could be inferred, is. Second, even if you don't know what variadic templates are, you can get a sense for what the code is doing in this case. It also has the nice aspect that it is about as minimal an implementation as you can get.
Note that you can't, in general, pass a function into a tuple iteration scheme like this if that functions execution at all depends on parameters to be pulled out of the tuple type. The behind the scenes detail here is that we are forcing a new 'evaluate' all to be created for every unique type in a given tuple at compile time (and then hopefully inlined).
The only thing I don't really like is that the inner function has to be named 'evaluate' or whatever the library uses. I'd be interested if anyone has a better idea for a name that is more in line with the standard library.