从右值无效初始化非常量引用 [英] invalid initialization of non-const reference from an rvalue

查看:252
本文介绍了从右值无效初始化非常量引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有以下功能:

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

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

I want to call it in different ways, like:

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

编译器抱怨std::ifstream("myfile")Handler()是作为非常量引用传递的右值,因此该抱怨是合法的,但是我该怎么办?

The compiler complains about std::ifstream("myfile") and Handler() of being rvalues being passed as non-const references, so the complaint is legitimate, but what can I do?

  1. 两个函数参数都不可以是const(istream在读取时被修改,并且处理程序在回调期间更改其状态).
  2. 如果将参数类型更改为右值引用(&&),则将无法传递std::cin,有时我真的很在意myhandler的最终状态,因此无法在它们上应用std::move两者都没有.
  3. 原则上,我可以通过模板或auto&&类型推导将参数设置为通用引用,并因此针对lvalue和rvalue引用的所有可能组合重载此函数,但是我无意将此函数重载给除I外的其他类型已经指定.
  1. Neither function parameters cannot be const (istream is modified while read and the handler changes its state during callbacks).
  2. If I change the parameter types to rvalue references (&&) then I will not be able to pass std::cin and sometimes I really care about the final state of myhandler thus I cannot apply std::move on them neither.
  3. In principle I could make the parameters as universal references via template or auto&& type deduction and thus overload this function for all possible combinations of lvalue and rvalue references, but I have no intention of overloading this function for other types than I have already specified.

还有其他选择吗?

在这样一个琐碎的例子中,整个动作的语义都以某种方式被阻碍了.

Somehow this whole move semantics got in the way in such a trivial example.

推荐答案

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

To convert an rvalue to an lvalue, you can use this lvalue helper function:

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

然后呼叫变为:

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

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

This is safe as the temporaries (the ifstream and Handler) aren't destructed until the end of the full expression. However, note that these are lvalue references to temporaries and as such you must use caution when deciding to use this method. I'm assuming the scan() doesn't hold references/pointers to the arguments after it returns.

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

For example, do not use it like this:

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

只需确保返回的引用的生存期与临时引用的生存期相对应,就可以了.

Just make sure the lifetime of the returned reference corresponds with the lifetime of the temporary, and you'll be fine.

这篇关于从右值无效初始化非常量引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆