从右值无效初始化非常量引用 [英] invalid initialization of non-const reference from an rvalue
问题描述
所以我有以下功能:
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?
- 两个函数参数都不可以是
const
(istream
在读取时被修改,并且处理程序在回调期间更改其状态). - 如果将参数类型更改为右值引用(
&&
),则将无法传递std::cin
,有时我真的很在意myhandler
的最终状态,因此无法在它们上应用std::move
两者都没有. - 原则上,我可以通过模板或
auto&&
类型推导将参数设置为通用引用,并因此针对lvalue和rvalue引用的所有可能组合重载此函数,但是我无意将此函数重载给除I外的其他类型已经指定.
- Neither function parameters cannot be
const
(istream
is modified while read and the handler changes its state during callbacks). - If I change the parameter types to rvalue references (
&&
) then I will not be able to passstd::cin
and sometimes I really care about the final state ofmyhandler
thus I cannot applystd::move
on them neither. - 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()));
这是安全的,因为临时变量(ifstream
和Handler
)在完整表达式结束之前不会被破坏.但是,请注意,这些是对临时变量的左值引用,因此,在决定使用此方法时必须格外小心.我假设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屋!