2016-07-31 103 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; 
相關問題