C 使用lambda进行隐式构造函数呼叫期望函数指针
C++ Using lambda for implicit constructor call expecting a function pointer
我试图从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;
}
https://godbolt.org/g/qe4v1z
[2]第5.1.2节中的C 14标准状态:
没有lambda捕获的lambda表达式的闭合类型具有公共非虚拟非宣传const constrion conversion函数,可指针具有具有相同参数和返回类型的函数,与闭合类型的函数呼叫运算符。此转换函数返回的值应为一个函数的地址,该函数在调用时具有与调用闭合类型的函数调用操作员相同的效果。
这意味着lambda应隐式(非阐释)转换为函数指针。
测试:
- Clang5.0.0 -Std = C 14
- msvc14.12/permissive-
是的,它是隐式转换为函数指针;这就是bool(*tmp)() = []() { return true; };
工作的原因。关键是,在一个隐式转换序列中,只允许使用一个用户定义的转换。
隐式转换序列由以下顺序组成:
- 零或一个标准转换序列;
- 零或一个用户定义的转换;
- 零或一个标准转换序列。
在考虑到构造函数或用户定义的论点时 转换功能,仅允许一个标准转换序列 (否则用户定义的转换可以有效链接)。
对于Foo f4 = [](){ return true; };
(即复制初始化),必须通过用户定义的lambda的用户转换函数将lambda转换为函数指针,然后通过Foo
的转换构造器转换为Foo
,需要两个用户定义的转换,并需要使用两个用户定义的转换。但不允许。
btw:
-
Foo f1 ( [](){ return true; });
起作用,因为对于直接的Intialization,Foo
的构造函数将直接调用;lambda转换为函数指针,然后作为参数传递给构造函数,这很好。 -
Foo f2 = Bar( [](){ return true; });
起作用,因为lambda明确转换为功能指针,该指针被隐式转换为Foo
。 -
bool(*tmp)() = []() { return true; }; Foo f3 = tmp;
起作用,因为lambda被隐式转换为函数指针为tmp
,然后tmp
转换为Foo
;任何一个隐式转换序列都只需要一个用户定义的转换,然后很好。 -
Foo f5 = +[](){ return true; };
工作是因为operator+
导致Lambda转换为函数指针,这意味着对于+[](){ return true; }
,您将使用类型bool(*)()
获得功能指针,然后故事与f2
相同。
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- 错误:呼叫构造器的匹配函数无匹配功能
- 匿名构造函数和击曲函数在矢量中呼叫
- 在类构造函数上没有匹配函数来呼叫错误
- C 使用lambda进行隐式构造函数呼叫期望函数指针
- 您能否防止构造函数的呼叫,而无需实例化
- C 错误:在自定义类的构造函数呼叫期间使用已删除的函数
- 在构造函数中呼叫迭代器会更改其最终值
- 如何执行移动构造函数(C )的呼叫