使用自动说明符获取lambda的参数类型

时间:2019-04-12 10:48:49

标签: c++ c++17 variadic-templates template-meta-programming generic-lambda

我有一个meta函数,该函数为我提供了lambda / function的第I个参数的类型:

#include <iostream>
#include <tuple>

namespace details
{
    //! Spezialization for Funktion-Pointers
    template<typename Ret, typename... Args>
    std::tuple<Args...> getArgs(Ret (*)(Args...));

    //! Spezialization for Functor/Lambdas
    template<typename F, typename Ret, typename... Args>
    std::tuple<Args...> getArgs(Ret (F::*)(Args...));

    //! Spezialization for Functor/Lambdas
    template<typename F, typename Ret, typename... Args>
    std::tuple<Args...> getArgs(Ret (F::*)(Args...) const);

}; // namespace details

template<typename F, std::size_t I>
using GetArg = std::tuple_element_t<I, decltype(details::getArgs(std::declval<F>()))>;

int main()
{
    auto f1 = [](int a, int b){};
    static_assert(std::is_same<GetArg<decltype(f1), 0>, int>{}, "Not the same!");

    // auto f2 = [](int a, auto b){};
    // static_assert(std::is_same<GetArg<decltype(f2), 0>, int>{}, "Not the same!");
}

Live

带有auto指示符的第二个lambda无法编译,因为我的序列化不匹配,因为auto就像模板参数T一样,尚不为人所知。 有没有一种方法可以使f2正常工作?

由于lambda是不透明类型,并且除非使用模板参数类型实例化,否则模板函数没有类型,所以我真的不知道如何实现此功能?不可能吗?

1 个答案:

答案 0 :(得分:0)

  

是否有一种方法可以使f2正常工作?

不,据我所知。

您几乎可以将通用lambda(具有一个或多个auto参数的lambda)作为模板函数(包装在类中)看到。

不包括类包装,您可以看到

[](int a, auto b){};

几乎与

template <typename T>
void foo (int a, T b)
 { };

您无法像完全根据b推导b的类型那样从lambda推导foo()的类型:确定调用函数(推导类型形成一个参数)或加以说明(例如foo<int>)。

但是,如果您仅编写decltype(foo),则编译器无法确定哪种类型是T,因此会出现错误。

无论如何,我也在编译时出错

static_assert(std::is_same<GetArg<decltype(f1), 0>, int>{}, "Not the same!");

我想您必须按如下所述写GetArg

using GetArg = std::tuple_element_t<I, decltype(details::getArgs(&F::operator()))>;
// ..............................................................^^^^^^^^^^^^^^

或者您可以保留实际的GetArg,但使用+f1调用

static_assert(std::is_same<GetArg<decltype(+f1), 0>, int>{}, "Not the same!");
// ........................................^^^

即将lambda转换为函数指针。