ami*_*421 3 c++ auto return-type-deduction c++14
由于自动推导了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;
}
Run Code Online (Sandbox Code Playgroud)
这里有两个问题。
首先,您实际上并未调用lambda,因此,您无需传递返回的值test,而是传递了函数对象,该对象显然是完全不兼容的类型!通过()在lambda之后添加来解决此问题,然后将返回值传递给test()。
[](){ return 42; } ();
// ^^ now the whole expression has value 42
Run Code Online (Sandbox Code Playgroud)
其次,您是对的,推导的返回类型将B不是B&,并且临时对象可能不绑定到的ref-to-non- constargument test(B&)。
解决此问题的一种方法是使用尾随返回类型来强制引用:
[&a]() -> B& { .... }
Run Code Online (Sandbox Code Playgroud)
您似乎知道这一点,但不想这样做。为什么?
另一个选择是返回一个引用包装,然后由值返回,但其行为类似于引用:
return std::ref(a.getB()));
Run Code Online (Sandbox Code Playgroud)
另一种选择是更改test为能够接受一些临时性的信息。由于您需要使用它来修改原始对象,因此可以test使用一个指针或具有引用语义的其他类型(智能指针a std::reference_wrapper<B>,B在复制它时请具有引用语义,...)
void test(B* b) {
++(b->i);
}
...
test([&]() { return &a.getB(); } () );
Run Code Online (Sandbox Code Playgroud)
给行人的注意事项:我知道++(b->i)绝对没有必要。我觉得更清楚。