![](/img/trans.png)
[英]template argument type deduction from std::function return type with 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,因此不是将返回值传递给test
,而是传递 function object,这显然是一个完全不兼容的类型! 通过在 lambda 之后添加()
来调用它,从而将返回值传递给test()
来解决这个问题。
[](){ return 42; } ();
// ^^ now the whole expression has value 42
其次,您是对的,推导的返回类型将是B
,而不是B&
,并且临时 object 可能不会绑定到test(B&)
的 ref-to-non- const
参数。
解决此问题的一种方法是使用尾随返回类型来强制引用:
[&a]() -> B& { .... }
你似乎知道这一点,但不想这样做。 为什么?
另一种选择是返回引用包装器,然后按值返回,但行为类似于引用:
return std::ref(a.getB()));
另一种选择是更改test
以能够接受一些临时的。 由于您需要它才能修改原始 object,因此您可以test
指针或具有引用语义的其他类型(智能指针、 std::reference_wrapper<B>
,使B
在复制时具有引用语义, ...)
void test(B* b) {
++(b->i);
}
...
test([&]() { return &a.getB(); } () );
学究的注意事项:我知道++(b->i)
中的括号并不是绝对必要的。 我觉得更清楚。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.