2016-07-31 233 views
5

我有下面的代码段,其中我定义struct quick与模板static方法random一些专业:(。我使用来自其他function_traits SO回答附于底部供参考)如何从参数包中获取所有参数的类型?

struct quick 
{ 
    template <typename T> 
    static T random(); 

    template <typename F> 
    static void check(F f) 
    { 

    constexpr auto arity = function_traits<F>::arity; // easy :) 
    std::cout << arity << std::endl; 
    typedef typename function_traits<F>::template arg<0>::type type0; // easy:) 
    // how to get all types of all F's parameters? 
    } 
}; 

template <> 
std::string quick::random<std::string>() 
{ 
    return std::string("test"); 
} 

template <> 
int quick::random<int>() 
{ 
    return 1; 
} 

我想获得所有类型的F的参数在check之内,这样我就可以用随机条目生成tuple(基于我的random方法专业化)。

像这样:

auto t0 = std::make_tuple(quick::random<AllTypes>()...); //pseudo code 
auto t = 
    std::make_tuple(quick::random < 
            function_traits<F>::template arg<std::make_index_sequence<arity>>::type... 
            > 
           ()... 
        ); 

我试过的东西,如:

template<typename F, typename ...TIdxs> 
using ArgTypes = typename function_traits<F>::template arg<TIdxs>::type...; 

// ... 
// inside check 

typedef ArgTypes<F, std::make_index_sequence<arity>> types; 

但悲惨地失败了:

main.cpp:80:72: error: expected ‘;’ before ‘...’ token 
using ArgTypes = typename function_traits<F>::template arg<TIdxs>::type...; 
                     ^
main.cpp: In static member function ‘static void quick::check(F, D)’: 
main.cpp:98:15: error: ‘ArgTypes’ does not name a type 
     typedef ArgTypes<F, std::make_index_sequence<arity>> types; 

我用function traits公用事业从this SO回答。

template <typename T> 
struct function_traits : function_traits<decltype(&T::operator())> 
{}; 
// For generic types, directly use the result of the signature of its 'operator()' 

template <typename ClassType, typename ReturnType, typename... Args> 
struct function_traits<ReturnType(ClassType::*)(Args...) const> 
// we specialize for pointers to member function 
{ 
    enum { arity = sizeof...(Args) }; 
    // arity is the number of arguments. 

    typedef ReturnType result_type; 

    template <size_t i> 
    struct arg 
    { 
     typedef typename std::tuple_element<i, std::tuple<Args...>>::type type; 
     // the i-th argument is equivalent to the i-th tuple element of a tuple 
     // composed of those arguments. 
    }; 
}; 
+0

像往常一样,功能特点onky作品有时。 'auto f = [](auto && x){return 2 * x;}'。关于'TIdxs'的 – Yakk

回答

-1

不确定这是你想要的,但是...怎么样在以下方式修改quick

struct quick 
{ 
    template <typename T> 
    static T random(); 

    template<typename F, std::size_t I> 
    using ArgTypes = typename function_traits<F>::template arg<I>::type; 

    template<typename F, std::size_t ... Is> 
    using ArgTuple = std::tuple< ArgTypes<F, Is>... >; 

    template <typename F, std::size_t ... Is> 
    static ArgTuple<F, Is...> makeArgTuple() 
    { return make_tuple(quick::random<Is>()...); } 

    template <typename F> 
    static void check(F f) 
    { 

    constexpr auto arity = function_traits<F>::arity; // easy :) 
    std::cout << arity << std::endl; 

    typedef typename function_traits<F>::template arg<0>::type type0; // easy:) 

    auto t = ArgTuple<F, std::make_index_sequence<arity>::type>(); 

    auto t2 = makeArgTuple<F, std::make_index_sequence<arity>::type>(); 
    } 

}; 

你错了传递typename小号TIdxsarg; arg需要std::size_t

考虑到std::make_index_sequence这是一个C++ 14功能(但它也很容易在C++ 11中创建它)。

对不起,我的英语不好。

+0

:但我想扩大它,以便我得到结果:'arg <0>,arg <1>,arg <2> ...' – Patryk

+0

@Patryk - 当然;但是作为'std :: size_t',而不是'typename';我的意思是:不是错的'template ';应该是'template ' – max66

+0

啊是啊。你是对的。但仍然无法得到我的最终结果'auto t = std :: make_tuple(quick :: random <... what_here ...>());' – Patryk

2
template<class=void,std::size_t...Is> 
auto tupler(std::index_sequence<Is...>){ 
    return [](auto&&f){ 
    return std::make_tuple(
     f(std::integral_constant<std::size_t,Is>{})... 
    ); 
    } 
} 
template<std::size_t N> 
auto tupler(){ 
    return tupler(std::make_index_sequence<N>{}); 
} 

这可以让你扩展参数包内联和产生一个元组。

只需

auto t = tupler<ArgCount>()([&](auto i){ 
    return random<typename func_trait::arg<i>::type>(); 
}); 

func_trait是一个别名上面的东西。

另外,用using替代struct arg别名。清洁器。

3

请注意,在function_traits中,您已经有所有的参数类型。所有你需要做的就是揭露他们:

template <typename ClassType, typename ReturnType, typename... Args> 
struct function_traits<ReturnType(ClassType::*)(Args...) const> 
// we specialize for pointers to member function 
{ 
    enum { arity = sizeof...(Args) }; 

    using result_type = ReturnType; 

    using all_args = std::tuple<Args...>; // <-- add this 

    template <size_t i> // <-- consider making this an alias template 
    using arg = std::tuple_element_t<i, all_args>; 
}; 

而现在,越来越所有函数的参数只是function_traits<F>::all_args


如果你不想改变function_traits,我们只需要添加一个外部元函数:

template <class F, class = std::make_index_sequence<function_traits<F>::arity>> 
struct all_args; 

template <class F, size_t... Is> 
struct all_args<F, std::index_sequence<Is...>> { 
    using type = std::tuple<typename function_traits<F>::template arg<Is>::type...>; 
}; 

template <class F> 
using all_args_t = typename all_args<F>::type;