防止 lambda 的返回类型扣除
prevent return type deduction of lambda
下面的代码由于从lambda返回的类型自动扣除而无法编译。
防止在 C++14 语法术语中没有尾随类型的这种推论的正确方法是什么?
编译错误是关于 test() 输入上的不兼容类型 (rvalue),它需要非常量引用
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
,而是传递函数对象,这显然是一个完全不兼容的类型!通过在 lambda 后添加()
来调用它来解决此问题,从而将返回值传递给test()
。
[](){ return 42; } ();
// ^^ now the whole expression has value 42
其次,你是对的,推导出的返回类型将是B
,而不是B&
,并且临时对象可能不受test(B&)
的引用到非const
参数的约束。
解决此问题的一种方法是使用尾随返回类型来强制引用:
[&a]() -> B& { .... }
你似乎知道这一点,但不想这样做。为什么?
另一种选择是返回一个引用包装器,然后按值返回,但行为类似于引用:
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函数的尾部返回类型
- 有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
- 如何推导lambda的返回类型
- 尽管显式声明了返回类型,但对lambda的调用是不明确的
- 是否创建具有不同返回类型的lambda
- 防止 lambda 的返回类型扣除
- 我可以让返回类型自动处理具有相同签名但捕获不同内容的 lambda 吗?
- 如何通过返回类型区分两个 lambda 函数?
- 如何在C++中比较 lambda 函数的返回类型?
- 获取模板函数/泛型 lambda 的唯一返回类型
- 尝试使用具有尾随返回类型的 lambda 进行 SFINAE 时出现硬错误
- 具有尾随返回类型的通用 lambda,具体取决于 C++11 中的可变参数
- IF-ELSE语句的Lambda表达式的返回类型扣除
- 在 C++14 中使用通用 lambda 和自动返回类型特征获得不同的结果
- 尝试传递 constexpr lambda 并使用它来显式指定返回类型
- 如何用clang格式分隔lambda的尾部返回类型
- 无法使用 std::map 推断 lambda 的返回类型
- 访问lambda尾随返回类型中的概括捕获对象
- 通用lambda,继承和尾随返回类型:此有效代码
- 是否可以通过从lambda的引用中返回T型对象,而无需使用尾随返回类型语法