所以我有以下功能:
void scan(std::istream& is, Handler& h);
我想以不同的方式调用它,例如:
scan(std::cin, Handler());
scan(std::ifstream("myfile"), myhandler);
编译器抱怨std::ifstream("myfile")
and Handler()
右值作为非常量引用传递,因此投诉是合法的,但我能做什么?
- 两个函数参数都不能是
const
(istream
在读取时被修改,并且处理程序在回调期间更改其状态)。
- 如果我将参数类型更改为右值引用(
&&
)那么我将无法通过std::cin
有时我真的很关心最终的状态myhandler
因此我无法申请std::move
对他们也没有。
- 原则上我可以通过模板或将参数作为通用参考
auto&&
类型推导,从而为左值和右值引用的所有可能组合重载此函数,但我无意为我已经指定的其他类型重载此函数。
还有其他选择吗?
不知何故,整个移动语义在这样一个微不足道的例子中出现了障碍。
要将右值转换为左值,可以使用此左值辅助函数:
template<class T>
T& lvalue_ref(T&& x) { return x; }
然后调用变成:
scan(lvalue_ref(std::ifstream("myfile")), lvalue_ref(Handler()));
这是安全的,因为临时者(ifstream
and Handler
) 在完整表达式结束之前不会被破坏。但是,请注意,这些是对临时变量的左值引用,因此在决定使用此方法时必须小心谨慎。我假设scan()
返回后不保存对参数的引用/指针。
例如,不要像这样使用它:
int& x = lvalue_ref(5);
std::cout << x; // temporary is destructed, therefore Undefined Behavior
只要确保返回引用的生命周期与临时引用的生命周期相对应,就可以了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)