簡體   English   中英

如何從通用模板<typename T>中提取lambda的Return Type和Variadic Parameters Pack

[英]How to extract lambda's Return Type and Variadic Parameters Pack back from general template<typename T>

我想創建一個模板化的類或函數,它接收一個lambda,並將它放在std :: function <>內部.Lambda可以有任意數量的輸入參數[](int a,float b,...)std :: function <>應該對應lambda的operator()的類型

template <typename T> 
void getLambda(T t) {
   // typedef lambda_traits::ret_type RetType; ??
   // typedef lambda_traits::param_tuple --> somehow back to parameter pack Args...
   std::function<RetType(Args...)> fun(t);
}

int main() {
    int x = 0;
    getLambda([&x](int a, float b, Person c){}); 
}

所以我需要以某種方式提取返回類型和參數包

這里的答案建議在lambda的:: operator()上使用部分規范

template <typename T>
struct function_traits : public function_traits<decltype(&T::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.
    };
};

但我需要一種方法將元組<>轉換回參數包,以創建一個正確的std :: function <>實例化

template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
    using result_type = ReturnType;
    using arg_tuple = std::tuple<Args...>;
    static constexpr auto arity = sizeof...(Args);
};

template <class F, std::size_t ... Is, class T>
auto lambda_to_func_impl(F f, std::index_sequence<Is...>, T) {
    return std::function<typename T::result_type(std::tuple_element_t<Is, typename T::arg_tuple>...)>(f);
}

template <class F>
auto lambda_to_func(F f) {
    using traits = function_traits<F>;
    return lambda_to_func_impl(f, std::make_index_sequence<traits::arity>{}, traits{});
}

上面的代碼應該做你想要的。 如您所見,主要思想是創建一個整數包。 這是variadics的非類型模板。 我不知道你可以使用這種方法而不調用另一個函數的任何技術,所以通常在這些帶有元組的情況下你會看到一個嵌套的“impl”函數來完成所有的工作。 獲得整數包之后,在訪問元組時展開它(用於獲取值)。

在風格上注意:使用using而不是typename尤其是在模板繁重的代碼中,因為前者也可以使用別名模板。 並且不使用該enum技巧來存儲靜態值而不使用空間; 編譯器無論如何都會優化它,只需使用static constexpr整數static constexpr清楚了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM