我有一个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!");
}
带有auto
指示符的第二个lambda无法编译,因为我的序列化不匹配,因为auto
就像模板参数T
一样,尚不为人所知。
有没有一种方法可以使f2
正常工作?
由于lambda是不透明类型,并且除非使用模板参数类型实例化,否则模板函数没有类型,所以我真的不知道如何实现此功能?不可能吗?
答案 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转换为函数指针。