防止 return lambda 的类型推导
prevent return type deduction of lambda
由于自动推导从 lambda 返回的类型,以下代码无法编译。
在没有尾随类型的 C++14 语法术语中防止这种推导的正确方法是什么?
编译错误是关于 test() 输入上的不兼容类型(右值),它需要非常量引用
struct B {
int i;
};
struct A {
B &getB() { return b; }
private:
B b;
};
void test(B &b) {
b.i++;
}
int main() {
A a;
test([&a]() {
return a.getB();
});
return 0;
}
这里有两个问题。
首先,您实际上并没有调用 lambda,因此您没有将 returned 值传递给 test
,而是传递函数对象,这显然是一个完全不兼容的类型!通过在 lambda 后面添加 ()
来解决这个问题,从而将 return 值传递给 test()
.
[](){ return 42; } ();
// ^^ now the whole expression has value 42
其次,你是对的,推导的 return 类型将是 B
,而不是 B&
,并且临时对象可能不会绑定到 ref-to-non- const
test(B&)
的参数。
解决此问题的一种方法是使用尾随 return 类型强制引用:
[&a]() -> B& { .... }
你似乎知道这一点,但不想去做。为什么?
另一种选择是 return 引用包装器,然后按值 return 编辑但表现得像引用:
return std::ref(a.getB()));
另一种选择是更改 test
以便能够接受一些临时的。因为你需要它来修改原始对象,你可以让 test
接受一个指针,或者其他具有引用语义的类型(一个智能指针,一个 std::reference_wrapper<B>
,使 B
有复制时引用语义,...)
void test(B* b) {
++(b->i);
}
...
test([&]() { return &a.getB(); } () );
书呆子注意事项:我知道 ++(b->i)
中的括号不是绝对必要的。我觉得更清楚了。
由于自动推导从 lambda 返回的类型,以下代码无法编译。
在没有尾随类型的 C++14 语法术语中防止这种推导的正确方法是什么?
编译错误是关于 test() 输入上的不兼容类型(右值),它需要非常量引用
struct B {
int i;
};
struct A {
B &getB() { return b; }
private:
B b;
};
void test(B &b) {
b.i++;
}
int main() {
A a;
test([&a]() {
return a.getB();
});
return 0;
}
这里有两个问题。
首先,您实际上并没有调用 lambda,因此您没有将 returned 值传递给 test
,而是传递函数对象,这显然是一个完全不兼容的类型!通过在 lambda 后面添加 ()
来解决这个问题,从而将 return 值传递给 test()
.
[](){ return 42; } ();
// ^^ now the whole expression has value 42
其次,你是对的,推导的 return 类型将是 B
,而不是 B&
,并且临时对象可能不会绑定到 ref-to-non- const
test(B&)
的参数。
解决此问题的一种方法是使用尾随 return 类型强制引用:
[&a]() -> B& { .... }
你似乎知道这一点,但不想去做。为什么?
另一种选择是 return 引用包装器,然后按值 return 编辑但表现得像引用:
return std::ref(a.getB()));
另一种选择是更改 test
以便能够接受一些临时的。因为你需要它来修改原始对象,你可以让 test
接受一个指针,或者其他具有引用语义的类型(一个智能指针,一个 std::reference_wrapper<B>
,使 B
有复制时引用语义,...)
void test(B* b) {
++(b->i);
}
...
test([&]() { return &a.getB(); } () );
书呆子注意事项:我知道 ++(b->i)
中的括号不是绝对必要的。我觉得更清楚了。