C ++非const rvalue参数解决方法

时间:2017-03-17 11:14:58

标签: c++ rvalue-reference

我有一些提供基本IO的Stream类。 我希望能够编写这样的代码:

Image img = Image(StreamReader("filepath"));

不幸的是,根据标准,将rvalue引用绑定到非const lvalue引用似乎是非法的,比如Image ctor的参数。

我不能使参数成为const引用,因为Streams需要更新它们的状态,例如:当前的扩张。

使这些Stream属性可变或者为它们构建它们对我来说似乎是糟糕的设计,因为这些状态对用户有明显的影响。

我有什么选择才能使这项工作,最好没有两个几乎相同的构造函数,每个'类似图像'类?

提前致谢。

1 个答案:

答案 0 :(得分:2)

  

我可以使用哪些选项来完成这项工作,最好不要为每个“类似图像”的类提供两个几乎相同的构造函数?

你想要perfect forwarding。它允许您定义一个同时接受const&&&

的函数
template <typename T, 
          typename std::enable_if_t<!std::is_same_v<std::decay_t<T>, Image>>>
Image::Image(T&& x)
{//          ^^^ 
 //          "forwarding reference"

    doSomething(std::forward<T>(x));
 //             ^^^^^^^^^^^^^^^^^^
 //             keep forwarding either as an rvalue reference or lvalue
 //             reference depending on the original value category of `x`
}

用法:

Image a{StreamReader("filepath")}; // rvalue

const StreamReader s("filepath");
Image b{s}; // const lvalue

StreamReader s2("filepath");
Image c{s2}; // lvalue

如果您想阻止const&被接受,您可以delete该特定重载,或将其添加到enable_if_t子句:

  • Image(const StreamReader&) = delete;

    (假设类型始终为StreamReader)。

  • std::enable_if_t<!std::is_const_v<T> && !std::is_same_v<std::decay_t<T>, Image>>