Skip to content

Instantly share code, notes, and snippets.

@Jiwan
Created July 10, 2014 16:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jiwan/a84f01ef95c145ca30cd to your computer and use it in GitHub Desktop.
Save Jiwan/a84f01ef95c145ca30cd to your computer and use it in GitHub Desktop.
A c++11 way to apply a map function to some tuples
/***** 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