How do I expand a tuple into variadic template function's arguments?

前端 未结 13 1009
旧时难觅i
旧时难觅i 2020-11-22 07:49

Consider the case of a templated function with variadic template arguments:

template Tret func(const T&... t);


        
相关标签:
13条回答
  • 2020-11-22 08:44

    In C++ there is many ways of expanding/unpacking tuple and apply those tuple elements to a variadic template function. Here is a small helper class which creates index array. It is used a lot in template metaprogramming:

    // ------------- UTILITY---------------
    template<int...> struct index_tuple{}; 
    
    template<int I, typename IndexTuple, typename... Types> 
    struct make_indexes_impl; 
    
    template<int I, int... Indexes, typename T, typename ... Types> 
    struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...> 
    { 
        typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type; 
    }; 
    
    template<int I, int... Indexes> 
    struct make_indexes_impl<I, index_tuple<Indexes...> > 
    { 
        typedef index_tuple<Indexes...> type; 
    }; 
    
    template<typename ... Types> 
    struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...> 
    {}; 
    

    Now the code which does the job is not that big:

     // ----------UNPACK TUPLE AND APPLY TO FUNCTION ---------
    #include <tuple>
    #include <iostream> 
    
    using namespace std;
    
    template<class Ret, class... Args, int... Indexes > 
    Ret apply_helper( Ret (*pf)(Args...), index_tuple< Indexes... >, tuple<Args...>&& tup) 
    { 
        return pf( forward<Args>( get<Indexes>(tup))... ); 
    } 
    
    template<class Ret, class ... Args> 
    Ret apply(Ret (*pf)(Args...), const tuple<Args...>&  tup)
    {
        return apply_helper(pf, typename make_indexes<Args...>::type(), tuple<Args...>(tup));
    }
    
    template<class Ret, class ... Args> 
    Ret apply(Ret (*pf)(Args...), tuple<Args...>&&  tup)
    {
        return apply_helper(pf, typename make_indexes<Args...>::type(), forward<tuple<Args...>>(tup));
    }
    

    Test is shown bellow:

    // --------------------- TEST ------------------
    void one(int i, double d)
    {
        std::cout << "function one(" << i << ", " << d << ");\n";
    }
    int two(int i)
    {
        std::cout << "function two(" << i << ");\n";
        return i;
    }
    
    int main()
    {
        std::tuple<int, double> tup(23, 4.5);
        apply(one, tup);
    
        int d = apply(two, std::make_tuple(2));    
    
        return 0;
    }
    

    I'm not big expert in other languages, but I guess that if these languages do not have such functionality in their menu, there is no way to do that. At least with C++ you can, and I think it is not so much complicated...

    0 讨论(0)
提交回复
热议问题