Created
September 5, 2014 21:44
-
-
Save Jiwan/380618c1b21291097ef2 to your computer and use it in GitHub Desktop.
A c++11 way to apply a map function to some tuples
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
/***** maptuple.cpp *****/ | |
#include <tuple> | |
#include <iostream> | |
#include <functional> | |
template<int ...S> struct indexes{}; | |
template<int N, int ...S> struct generate_indexes : generate_indexes<N - 1, N - 1, S...> {}; | |
template<int ...S> struct generate_indexes<0, S...> { | |
typedef indexes<S...> type; | |
}; | |
/***** Apply a function to all the elements of a tuple *****/ | |
template<template<class> class F, typename ...Args> class _apply_tuple | |
{ | |
private: | |
std::tuple<Args...>& _tuple; | |
public: | |
_apply_tuple(std::tuple<Args...>& tuple): _tuple(tuple) { } | |
void operator()() { | |
typedef typename generate_indexes<sizeof...(Args)>::type indexes; | |
do_map((indexes())); | |
} | |
template<int ...S> void do_map(indexes<S...>) { | |
_do_map(std::get<S>(_tuple) ...); | |
} | |
template<typename Arg> void _do_map(Arg arg) { | |
F<Arg>::apply(arg); | |
} | |
template<typename Arg, typename ...Argz> void _do_map(Arg arg, Argz... args) { | |
F<Arg>::apply(arg); | |
_do_map(args...); | |
} | |
}; | |
template<template<class> class F, typename ...Args> inline void apply_tuple(std::tuple<Args...>& tuple) | |
{ | |
(_apply_tuple<F, Args...>(tuple))(); | |
} | |
/***** Apply a function to all the elements of a tuple and create a new tuple from the return values *****/ | |
template<template<class> class F, typename ...Args> class _map_tuple | |
{ | |
private: | |
std::tuple<Args...>& _tuple; | |
public: | |
_map_tuple(std::tuple<Args...>& tuple): _tuple(tuple) { } | |
std::tuple<Args...> operator()() { | |
typedef typename generate_indexes<sizeof...(Args)>::type indexes; | |
return do_map((indexes())); | |
} | |
template<int ...S> std::tuple<Args...> do_map(indexes<S...>) { | |
return std::make_tuple(F<Args>::apply(std::get<S>(_tuple)) ...); | |
} | |
}; | |
template<template<class> class F, typename ...Args> inline std::tuple<Args...> map_tuple(std::tuple<Args...>& tuple) | |
{ | |
return (_map_tuple<F, Args...>(tuple))(); | |
} | |
/***** test.cpp *****/ | |
#include <string> | |
#include <maptuple.hpp> | |
template<typename V> struct magicChange | |
{ | |
static V apply(V value) | |
{ | |
return value; | |
} | |
}; | |
template<> struct magicChange<int> | |
{ | |
static int apply(int value) | |
{ | |
return 1337; | |
} | |
}; | |
template<> struct magicChange<std::string> | |
{ | |
static std::string apply(std::string value) | |
{ | |
if (value == "template") | |
{ | |
return "my"; | |
} | |
else if (value == "metaprogramming") | |
{ | |
return "self"; | |
} | |
else | |
{ | |
return value; | |
} | |
} | |
}; | |
template<typename V> struct printer { | |
static void apply(V value) | |
{ | |
std::cout << value << " "; | |
} | |
}; | |
int main() | |
{ | |
auto car = std::make_tuple("I", "love", std::string("template"), std::string("metaprogramming"), 2); | |
auto bus = map_tuple<magicChange>(car); | |
apply_tuple<printer>(bus); | |
std::cout << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment