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