【发布时间】:2017-12-07 14:57:19
【问题描述】:
我正在尝试从 lambda 函数隐式构造一个对象。对象的构造函数将函数指针作为参数。但是代码 [ 1 ] 没有与消息一起编译:
6 : <source>:6:5: note: candidate constructor not viable: no known conversion from '(lambda at /tmp/compiler-explorer-compiler117117-54-dfxyju.lkw98/example.cpp:22:14)' to 'Bar' (aka 'bool (*)()') for 1st argument
Foo(Bar b) : m_b{b} {}
但标准规定 lambda 函数可以隐式转换为具有相同参数和返回类型 [2] 的函数指针。这应该适用于此,因此我希望构造函数是可调用的。
那么为什么代码不能编译呢?感谢您的解释!
[1]代码示例:
using Bar = bool(*)();
class Foo
{
public:
Foo(Bar b) : m_b{b} {}
private:
Bar m_b;
};
int main()
{
// working
Foo f1 ( [](){ return true; });
Foo f2 = Bar( [](){ return true; });
// working implicit conversion
bool(*tmp)() = []() { return true; };
Foo f3 = tmp;
// not working
Foo f4 = [](){ return true; };
return 0;
}
[ 2 ] C++14 Standard 在第 5.1.2 节中声明:
没有 lambda-capture 的 lambda 表达式的闭包类型有一个公共的非虚拟非显式 const 转换函数,指向具有与闭包类型的函数调用运算符相同的参数和返回类型的函数的指针。这个转换函数的返回值应该是一个函数的地址,当被调用时,它与调用闭包类型的函数调用运算符具有相同的效果。
这意味着 lambda 应该隐式(非显式)转换为函数指针。
测试:
- Clang5.0.0 -std=c++14
- MSVC14.12 /permissive-
【问题讨论】:
-
有趣的是,这行得通:
Foo f4 = +[](){ return true; };
标签: c++ c++11 lambda c++14 language-lawyer