繁体   English   中英

在模板中匹配 C++ lambda 表达式

[英]Matching a C++ lambda expression in templates

我正在尝试匹配 C++ 模板中的可调用对象,并根据作为参数接收的可调用对象的类型提供不同的实现。

我有以下模板函数:

template<class Ret, class... Args>
void fun(std::function<Ret(Args...)> f) {}

template<class Ret, class... Args>
void fun(Ret(*f)(Args...)) {}

它们接受std::function对象和普通函数指针,并正确推导出它们的返回Ret和参数Args类型。 但是,我很难传递匿名 lambda 表达式,因为它们与上面的任何模板都不匹配。

调用类似的东西

fun([](int x, int y){return x + y;})

导致编译错误。 实现接受匿名 lambda 函数的模板表达式的正确方法是什么? 也许一种方法是检查传递的类是否具有operator()方法?

转换发生在模板参数替换之后。 lambda 的类型不是std::function ,而是匿名类型。 实际上,您将收到一个匿名 lambda 以接收任何可调用对象。

似乎您担心的是限制接收到的对象来定义operator() 这个问题很容易用表达式 sfinae 解决。 但是,由于您没有收到参数,因此很难检查表达式是否有效。

这不是一个通用示例,但它适用于任何没有auto作为其参数之一的 lambda,或者任何没有重载operator()对象:

template<typename F>
auto fun(F f) -> void_t<decltype(&T::operator())> {
    // ...
}

void_t实现如下:

template<typename...>
using void_t = void;

decltype的表达式必须有效才能使函数存在。

如果您希望代码使用更多类型,则必须提供可以指定参数的重载。 该检查现在很容易实现:

// Another overload of your function
template<typename F, typename... Args>
auto fun(F f) -> void_t<decltype(f(std::declval<Args>()...)> {
    // ...
}

这样,它也适用于泛型 lambda 和重载运算符。

这是有效的 C++ 代码,C++14 级别的 gcc 6.1.1 将支持我:

template<typename F>
void foo(F &&f)
{
}

void bar()
{
    auto lambda=[](auto a, auto b) {};

    foo(lambda);
}

如您所见,模板不可能推导出 lambda 的参数。 lambda 的参数类型在使用之前是未知的。

您可以推断出某个东西有一个operator() ,正如另一个答案所示,但就目前而言,这已经差不多了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM