Skip to content

Instantly share code, notes, and snippets.

@mfukar
Created April 30, 2016 04:56
Embed
What would you like to do?
Use an std::tuple without magic numbers and the stupid get<> interface
#include <tuple>
struct Cache;
template<int, typename> struct cache_getter;
template<int, typename...> struct tuple_walker;
template<int I, typename... Ts> struct cache_getter<I, std::tuple<Ts...> > {
static std::tuple<Ts...> get(Cache & c);
};
struct Cache {
protected:
template<int, typename...> friend struct tuple_walker;
private:
/* here T is a type from within a std::tuple<...> */
template<int I, typename T> std::tuple<T> get_ex() {
return std::tuple<T>();
}
public:
/* here T is actually a std::tuple<...> */
template<typename T> T get() {
return cache_getter<0, T>::get(*this);
}
};
template<typename...> struct my_tuple_cat;
template<typename H, typename... T> struct my_tuple_cat<H, T...> {
static auto cat(H h, T... t) -> decltype(std::tuple_cat(h, my_tuple_cat<T...>::cat(t...)))
{ return std::tuple_cat(h, my_tuple_cat<T...>::cat(t...)); }
};
template<typename T> struct my_tuple_cat<T> {
static T cat(T t) { return t; }
};
template<int I, typename H, typename... T> struct tuple_walker<I, H, T...> {
static std::tuple<H, T...> get(Cache & c) {
return my_tuple_cat<std::tuple<H>, std::tuple<T...>>::cat(c.get_ex<I, H>(), tuple_walker<I + 1, T...>::get(c));
}
};
template<int I, typename H> struct tuple_walker<I, H> {
static std::tuple<H> get(Cache & c) {
return c.get_ex<I, H>();
}
};
template<int I, typename... Ts> std::tuple<Ts...> cache_getter<I, std::tuple<Ts...> >::get(Cache & c) {
return tuple_walker<I, Ts...>::get(c);
}
int main(int argc, char ** argv) {
Cache cache;
typedef std::tuple<int, double, bool> InstrumentTuple;
InstrumentTuple tuple = cache.get<InstrumentTuple>();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment