问题 为什么这个lambda可以流动?


令我惊讶的是,以下代码打印出来 1

std::cout << [](const char* arg){ return arg[0]=='s'; } << std::endl;

有人可以解释一下吗?


7392
2017-07-10 02:31


起源

我认为它正在转变为 bool。 - jtbandes
有趣的部分是如果 std::cin >> [](const char* arg){ return arg[0]=='s'; } 工作。 ;) - Yakk - Adam Nevraumont


答案:


它转换为函数指针,然后通过它转换为bool:

void foo ();
std::cout << &foo << std::endl;

打印相同的东西和相同的警告;我碰巧用gcc设置为17标准编译,我看到:

main.cpp:6:56: warning: the address of 'static constexpr bool main()::<lambda(const char*)>::_FUN(const char*)' will never be NULL [-Waddress]
  std::cout << [](const char* arg){ return arg[0]=='s'; } << std::endl;

使用上面的代码,您会看到相同的警告。

添加一点我的答案:有一个流重载 void*。但是,与指向数据的指针不同,函数指针不能隐式转换为 void*。函数指针的唯一隐式转换是boolean,当然还有bool的流操作,因此选择了重载并发生隐式转换。看到: 如何用cout打印函数指针?


12
2017-07-10 02:35



@ M.M lambda首先转换为函数指针,然后通过它转换为bool。我实际上并不知道函数指针在流式传输时转换为bools,而实际上并不奇怪。 - Nir Friedman
@NirFriedman这是完全合理的。根据标准当前工作草案的8.1.5.1(6),无捕获的lambda具有指向函数的转换运算符,并且每7.14指针可以是 隐式 转为布尔。关键点在于第二次转换是隐式发生的,这就是允许两次转换的原因。如果是第二次用户定义的转换,则不会发生。 - Henri Menke
@HenriMenke由于lambdas函数不是真正的“用户定义”,我有点惊讶lambda - >函数指针被视为用户定义的转换。但是,是的,我关于函数指针被视为布尔流的评论只是说乍一看似乎有点令人惊讶(并且不是很有用)。一旦你认为它更有意义,只是一个令人惊讶的行为的例子,从几个合理的事情会议出现。 - Nir Friedman