我尝试做的是在构造可能无效的对象时吃异常。它对于std::optional
的使用是完美的,但我不相信std::optional
的遗漏会改变我看到的错误:在初始化对象之前捕获并使用该对象。我不相信它应该首先捕获,因为我们还没有达到序列点我知道(lambda初始化计数作为序列点吗?)。此外,该错误是IMO易于捕获的人为错误(甚至会被捕获......取决于具体情况)。
如何(更重要的是,为什么)是lambda能够捕获并使用尚未初始化的foo
?
#include <string>
using namespace std;
void foo() {
string foo = [&]()->string{
// using foo before it's been initialized == undefined behavior
auto guessed_foo = to_string(1234);
if ( begin(foo) == end(foo) ) {
return guessed_foo;
}
return {};
}();
}
编译器退出,结果代码为0
但是......用string foo
替换auto foo
的声明似乎会导致类似于我希望看到的错误。
#include <string>
using namespace std;
void foo() {
auto foo = [&]()->string{
auto guessed_foo = to_string(1234);
if ( begin(foo) == end(foo) ) {
return guessed_foo;
}
return {};
}();
}
错误:使用'auto'类型声明的变量'foo'不能出现在自己的初始化程序中
请注意,我在Ubuntu 16.04 LTS上使用GCC 6.2发现了这一点。 Godbolt中的配置使用了clang 3.9.1。两者都配置为c ++ 14。
所以我的问题是:
auto
(在我看来,正确地)得到了错误?auto
关键字?答案 0 :(得分:2)
第二个代码段会遇到[dcl.spec.auto]/10:
如果需要具有未减少占位符类型的实体的类型 为了确定表达式的类型,程序是不正确的。
需要foo
的类型来确定lambda体内表达式foo
的类型,但此时您还没有推断foo
&#39; s类型,所以该程序是不正确的。
关于为什么允许在初始化之前捕获某些内容,请参阅Why is 'int i = i;' legal?。我们有很多使用std::function
递归lambda的例子:
std::function<void(int)> foo = [&foo](int i){ return foo(i - 1); };