在模板中匹配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()
定义。这个问题很容易用表达式约束来解决。但是,由于没有接收参数,因此很难检查表达式是否有效。
这不是一个通用的例子,但它将适用于任何没有将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()
,正如另一个答案所示,但这几乎就是它的极限了。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 可组合的lambda/std::函数与std::可选
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 如何将lambda作为模板类的成员函数参数
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 在 lambda 捕获中声明的变量的类型推导
- 我可以将调用类的"this"传递给 lambda 函数吗?
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 模板函数指针和lambda
- 两组使用lambda函数的大括号
- 使lambda不可复制/不可移动
- FLTK:按下哪个按钮 - 将数字传递给按钮的回调 (lambda)
- 尝试将lambda函数放在队列中时出现一般分配器错误(可能是与unique_ptr有关的错误)
- 将带有unique_ptr的可变 lambda 传递给 const&std::function
- AWS Lambda C++运行时权限被拒绝
- 捕获lambda中的std::数组
- 这 4 个 lambda 表达式之间有什么区别?
- 在实现文件中使用头文件的通用 lambda
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?