c++ - 来自右值的非常量引用的无效初始化

标签 c++ c++11 c++14 rvalue-reference type-deduction

所以我有以下功能:

void scan(std::istream& is, Handler& h);

我想用不同的方式调用它,比如:

scan(std::cin, Handler());
scan(std::ifstream("myfile"), myhandler);

编译器提示 std::ifstream("myfile")Handler() 是作为非常量引用传递的右值,所以提示是合法的, 但我能做什么呢?

  1. 两个函数参数都不能是 const(istream 在读取时被修改并且处理程序在回调期间更改其状态)。
  2. 如果我将参数类型更改为右值引用 (&&) 那么我将无法通过 std::cin 并且有时我真的很关心最终状态myhandler 因此我不能对它们应用 std::move
  3. 原则上,我可以通过模板或 auto&& 类型推导将参数作为通用引用,从而为左值和右值引用的所有可能组合重载此函数,但我无意重载此函数对于我已经指定的其他类型。

还有其他选择吗?

在这样一个微不足道的例子中,整个移动语义不知何故受到了阻碍。

最佳答案

要将右值转换为左值,您可以使用这个左值辅助函数:

template<class T>
T& lvalue_ref(T&& x) { return x; }

然后调用变成:

scan(lvalue_ref(std::ifstream("myfile")), lvalue_ref(Handler()));

这是安全的,因为临时对象(ifstreamHandler)在完整表达式结束之前不会被破坏。但是,请注意,这些是对临时对象的左值引用,因此在决定使用此方法时必须谨慎。我假设 scan() 在返回后不保存对参数的引用/指针。

例如,不要这样使用:

int& x = lvalue_ref(5);
std::cout << x; // temporary is destructed, therefore Undefined Behavior

只需确保返回引用的生命周期与临时引用的生命周期相对应,就可以了。

关于c++ - 来自右值的非常量引用的无效初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35439619/

相关文章:

c++ - 你对 typedef'ing shared_ptr 的约定是什么?

python - 白底跟踪白球(Python/OpenCV)

c++ - 解释为什么这个未简化的复杂性表达式是这样的?

c++ - 按对象数据成员属性搜索对象 vector

c++ - 我可以使用 C++11 大括号初始化语法来避免为简单聚合声明琐碎的构造函数吗?

c++ - 为什么通过 const 引用传递 constexpr 对象有效,但按值不编译

c++ - 使用 std::vector<> 和 std::shared_ptr<> 会导致错误

C++ 构造函数 : Perfect forwarding and overload

C++ 函数包装器捕获特定信号

c++ - 从内部类调用模板函数