Search code examples
c++c++11tuplesfunctoriterable-unpacking

unpacking, function application, and packing tuples in C++0X


What is the best way to write the readvals function in the following code without using Boost? Basically, it should get a tuple, call a specific function of it's elemets and return the generated results as a tuple again.

Is there any C++0X-based Functor definition library for tuples?

template <class T>
struct A
{
    A(T _val):val(_val){}
    T ret() {return val;}
    T val;
};

template <typename... ARGS>
std::tuple<ARGS...> readvals(std::tuple<A<ARGS>...> targ)
{
    //???
}

int main(int argc, char **argv)
{
    A<int> ai = A<int>(5);
    A<char> ac = A<char>('c');
    A<double> ad = A<double>(0.5);


    std::tuple<A<int>,A<char>,A<double>> at = std::make_tuple(ai,ac,ad);

    // assuming proper overloading of "<<" for tuples exists
    std::cout << readvals<int,char,double>(at) << std::endl;
    // I expect something like (5, c, 0.5) in the output
    return 0;
}

I have found questions on SO which deal partly with this problem (tuple unpacking, iterating over tuple elements, etc.), but it seems to me that there should be an easier solution compared to putting together all such solutions.


Solution

  • Is this what you are looking for? I hope you can at least use it as a starting point. There are just more ways to approach working with tuples and variadic templates than there are ways that lead to rome...

    #include <iostream>
    #include <tuple>
    
    template<class T>
    struct A
    {
        T t;
        A( const T& t_ ) : t(t_) { }
    };
    
    template<class T>
    T func( const A<T>&  t)
    {
        std::cout << __PRETTY_FUNCTION__ << " " << t.t << "\n";
        return t.t;
    }
    
    template<size_t N,class R,  class T>
    struct genh
    {
        static void gen( R& ret, const T& t )
        {
            std::cout << __PRETTY_FUNCTION__ << "\n";
            genh<N-1,R,T>::gen(ret,t);
            std::get<N>(ret) = func(std::get<N>(t));
        }
    };
    
    template<class R, class T>
    struct genh<0,R,T>
    {
        static void gen( R& ret, const T& t )
        {
            std::cout << __PRETTY_FUNCTION__ << "\n";
            std::get<0>(ret) = func(std::get<0>(t));
        }
    };
    
    template<class... T>
    std::tuple<T...> readvals( const std::tuple<A<T>...>& targ )
    {
        std::tuple<T...> ret;
        genh<sizeof...(T)-1,std::tuple<T...>,std::tuple<A<T>...>>::gen(ret,targ);
        return ret;
    }
    
    int main(int argc, const char *argv[])
    {
        A<int> ai = A<int>(5);
        A<char> ac = A<char>('c');
        A<double> ad = A<double>(0.5);
    
    
        std::tuple<A<int>,A<char>,A<double>> at = std::make_tuple(ai,ac,ad);
    
        readvals(at);
        return 0;
    }