【问题标题】:C++ Using lambda for implicit constructor call expecting a function pointerC ++使用lambda进行隐式构造函数调用,期望函数指针
【发布时间】: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;
}

https://godbolt.org/g/QE4v1Z


[ 2 ] C++14 Standard 在第 5.1.2 节中声明:

没有 lambda-capture 的 lambda 表达式的闭包类型有一个公共的非虚拟非显式 const 转换函数,指向具有与闭包类型的函数调用运算符相同的参数和返回类型的函数的指针。这个转换函数的返回值应该是一个函数的地址,当被调用时,它与调用闭包类型的函数调用运算符具有相同的效果。

这意味着 lambda 应该隐式(非显式)转换为函数指针。


测试:

  • Clang5.0.0 -std=c++14
  • MSVC14.12 /permissive-

【问题讨论】:

标签: c++ c++11 lambda c++14 language-lawyer


【解决方案1】:

是的,它隐式转换为函数指针;这就是bool(*tmp)() = []() { return true; }; 起作用的原因。重点是在一个implicit conversion sequence中,只允许一个用户自定义的转换。

隐式转换序列包含以下内容,按此顺序:

  1. 零个或一个标准转换序列;
  2. 零次或一次用户定义的转换;
  3. 零个或一个标准转换序列。

当考虑构造函数或用户定义的参数时 转换函数,只允许一个标准转换序列 (否则用户定义的转换可能会被有效地链接起来)。

对于Foo f4 = [](){ return true; };,即copy initializationlambda必须通过lambda的自定义转换函数转换为函数指针,再通过Foo的转换构造函数转换为Foo ,需要两次用户定义的转换,但不允许。

顺便说一句:

  1. Foo f1 ( [](){ return true; }); 有效,因为对于direct intializationFoo 的构造函数将被直接调用;将lambda转换为函数指针,然后作为参数传递给构造函数,这很好。

  2. Foo f2 = Bar( [](){ return true; }); 有效,因为 lambda 显式转换为函数指针,函数指针稍后隐式转换为 Foo

  3. bool(*tmp)() = []() { return true; }; Foo f3 = tmp; 有效,因为 lambda 被隐式转换为函数指针为tmp,然后tmp 被转换为Foo;任一隐式转换序列只需要一个用户定义的转换,就可以了。

  4. Foo f5 = +[](){ return true; }; 起作用是因为operator+ 导致lambda converted to function pointer,这意味着对于+[](){ return true; },您将获得类型为bool(*)() 的函数指针,那么故事与f2 相同。

【讨论】:

  • 或构造函数模板。
猜你喜欢
  • 2018-04-16
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 2013-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多