【问题标题】:assigning lambda to std::function将 lambda 分配给 std::function
【发布时间】:2012-11-03 19:21:40
【问题描述】:

当推断的返回类型为 std::nullptr_t 时,为什么允许第二次赋值?对于函数指针,这是禁止的。

为什么第二个 lambda 不运行?

#include <cstdio>
#include <functional>

int main()
{
    std::function<void* ()> f;

    f = []() -> void* {
        printf ("runs\n");
        return nullptr;
    };
    f();

    f = []() {
        printf ("doesn't run\n");
        return nullptr; // -> std::nullptr_t
    };
    f();

    return 0;
}

【问题讨论】:

  • 好吧,nullptr 与 void* 是协变的,所以应该没问题。
  • 它有什么“禁忌”?函数指针在哪里?
  • @Lightness:我认为他的意思是您不能将第二个 lambda 分配给 void* (pf)()
  • @Xeo:好的,我支持你。他没想到推断的返回类型是兼容的,这对于真正的函数指针是正确的。

标签: c++ lambda c++11 implicit-conversion std-function


【解决方案1】:

std::function 允许您存储任何内容,只要您提供的签名符合以下条件:

  • 所有参数类型都可以隐式转换为存储的可调用实体的参数类型,并且
  • 存储的可调用实体的返回类型可隐式转换为签名的返回类型

std::nullptr_t 可隐式转换为任何指针类型,并产生该指针类型的空指针值。

请注意,您的代码实际上不是有效的 C++11,因为您在第二个 lambda 中不仅有 return expr;,因此不会发生返回类型推导。 GCC(和 Clang、IIRC)将此作为扩展来实现,因为它会在某个时候成为标准的一部分。

【讨论】:

  • 那么第二个问题呢,为什么第二个 lambda 没有运行?这确实令人费解。
  • @icepack:确实如此,我目前正在调查。 MSVC 产生相同的行为。
  • 5.1.2(4) "如果 lambda 表达式不包含尾随返回类型,则好像尾随返回类型表示以下类型:- 如果复合-语句的格式为 { attribute-specifier-seqoptreturn expression ; } ...snip... — 否则,void。"
  • 因此,由于返回类型为 void,因此 lambda 与 std::function 不兼容,因此认为自己为空。
  • @rici:如果std::function 为空,您将收到bad_function_call 异常。此外,如果返回类型推断为 void 并且您在 lambda 的主体中有一个 return something;,那么在此之前您会收到一个错误。在 OP 的情况下,GCC 扩展解决了这个问题。另外,即使指定了返回类型,代码也不会运行:liveworkspace.org/code/e4d8408d456c5227ce715a7740877fec
猜你喜欢
  • 2018-03-11
  • 2016-12-18
  • 2021-12-27
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多