所以我有以下功能:
void scan(std::istream& is, Handler& h);
我想以不同的方式称呼它,例如:
scan(std::cin, Handler());
scan(std::ifstream("myfile"), myhandler);
编译器抱怨std::ifstream("myfile")
和Handler()
被rvalues作为非const引用传递,因此投诉是合法的,但我该怎么办?
const
(istream
在读取时被修改,处理程序在回调期间更改其状态。)&&
),那么我将无法通过std::cin
,有时我真的关心myhandler
的最终状态,因此我无法也不对他们适用std::move
。auto&&
类型推导使参数成为通用引用,从而为lvalue和rvalue引用的所有可能组合重载此函数,但我无意为其他类型重载此函数比我已经指定的那样。还有其他选择吗?
不知何故,整个移动语义在这样一个微不足道的例子中受到阻碍。
答案 0 :(得分:6)
要将右值转换为左值,您可以使用此左值辅助函数:
template<class T>
T& lvalue_ref(T&& x) { return x; }
然后电话变为:
scan(lvalue_ref(std::ifstream("myfile")), lvalue_ref(Handler()));
这是安全的,因为临时(ifstream
和Handler
)在完整表达结束之前不会被破坏。但请注意,这些是对临时值的左值引用,因此在决定使用此方法时必须谨慎。我假设scan()
在返回后不会保留对参数的引用/指针。
例如,不要像这样使用它:
int& x = lvalue_ref(5);
std::cout << x; // temporary is destructed, therefore Undefined Behavior
只需确保返回引用的生命周期与临时引用的生命周期相符,您就可以了。