Created
July 10, 2014 16:08
-
-
Save Jiwan/a84f01ef95c145ca30cd 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 2; | |
} | |
}; | |
template<> struct magicChange<std::string> | |
{ | |
static std::string apply(std::string value) | |
{ | |
if (value == "boîte") | |
{ | |
return "bite"; | |
} | |
else if (value == "coquilles") | |
{ | |
return "couilles"; | |
} | |
else | |
{ | |
return value; | |
} | |
} | |
}; | |
template<typename V> struct printer { | |
static void apply(V value) | |
{ | |
std::cout << value << " "; | |
} | |
}; | |
int main() | |
{ | |
auto car = std::make_tuple("J'ai", std::string("mangé"), "une", std::string("boîte"), "d'escargots", "mais", "j'ai", "oublié", "d'enlever", std::string("les"), 10, std::string("coquilles")); | |
auto bus = map_tuple<magicChange>(car); | |
std::cout << "Après correction: " << std::endl; | |
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