从右值初始化非const引用无效

时间:2016-02-16 17:49:18

标签: c++ c++11 c++14 rvalue-reference type-deduction

所以我有以下功能:

void scan(std::istream& is, Handler& h);

我想以不同的方式称呼它,例如:

scan(std::cin, Handler());
scan(std::ifstream("myfile"), myhandler);

编译器抱怨std::ifstream("myfile")Handler()被rvalues作为非const引用传递,因此投诉是合法的,但我该怎么办?

  1. 两个函数参数都不能constistream在读取时被修改,处理程序在回调期间更改其状态。)
  2. 如果我将参数类型更改为右值引用(&&),那么我将无法通过std::cin,有时我真的关心myhandler的最终状态,因此我无法也不对他们适用std::move
  3. 原则上我可以通过模板或auto&&类型推导使参数成为通用引用,从而为lvalue和rvalue引用的所有可能组合重载此函数,但我无意为其他类型重载此函数比我已经指定的那样。
  4. 还有其他选择吗?

    不知何故,整个移动语义在这样一个微不足道的例子中受到阻碍。

1 个答案:

答案 0 :(得分:6)

要将右值转换为左值,您可以使用此左值辅助函数:

template<class T>
T& lvalue_ref(T&& x) { return x; }

然后电话变为:

scan(lvalue_ref(std::ifstream("myfile")), lvalue_ref(Handler()));

这是安全的,因为临时(ifstreamHandler)在完整表达结束之前不会被破坏。但请注意,这些是对临时值的左值引用,因此在决定使用此方法时必须谨慎。我假设scan()在返回后不会保留对参数的引用/指针。

例如,不要像这样使用它:

int& x = lvalue_ref(5);
std::cout << x; // temporary is destructed, therefore Undefined Behavior

只需确保返回引用的生命周期与临时引用的生命周期相符,您就可以了。