所以我有以下功能:
void scan(std::istream& is, Handler& h);
我想用不同的方式来称呼它,例如:
scan(std::cin, Handler());
scan(std::ifstream("myfile"), myhandler);
编译器抱怨std::ifstream("myfile")
并将Handler()
rvalue作为非const引用传递,因此该抱怨是合法的,但是我该怎么办?
const
(istream
同时读取和处理程序的回调过程中改变其状态被修改)。&&
),则将无法通过std::cin
,有时我真的很在乎最终状态,myhandler
因此我也无法将std::move
其应用于任何状态。auto&&
类型推导将参数设置为通用引用,从而对lvalue和rvalue引用的所有可能组合都重载此函数,但是我没有打算针对除我已经指定的其他类型重载此函数。还有其他选择吗?
在这样一个琐碎的例子中,整个动作的语义都以某种方式被阻碍了。
要将右值转换为左值,可以使用以下左值辅助函数:
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
只要确保返回的引用的生存期与临时生存期相对应,就可以了。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句