C++ 非 const 右值参数解决方法

Posted

技术标签:

【中文标题】C++ 非 const 右值参数解决方法【英文标题】:C++ non const rvalue parameter workaround 【发布时间】:2017-03-17 11:14:57 【问题描述】:

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

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

不幸的是,根据标准,将右值引用绑定到非 const 左值引用似乎是非法的,就像 Image ctor 的参数一样。

我不能将参数设为 const 引用,因为 Streams 需要更新它们的状态,例如当前流位置。

将这些 Stream 属性设置为可变或 const 对我来说似乎是糟糕的设计,因为这些状态对用户有明显的影响。

我必须有哪些选项才能完成这项工作,最好不要为每个“类似图像”的类提供两个几乎相同的构造函数?

提前致谢。

【问题讨论】:

转发参考? 您提到了两个几乎相同的构造函数。你的其他构造函数是什么样的? 我的意思是没有一个构造函数采用左值和一个采用右值。 啊。我误解了这个问题。 TBH 我只会添加两个构造函数,而不是乱用完美的转发。您可以通过调用StreamReader& 重载来实现StreamReader&& 重载。亲吻。 您似乎使用了StreamReader,只提供采用StreamReader&& 的构造函数可能有意义(因此当它还不是临时的时,强制用户使用std::move)。 【参考方案1】:

我必须有哪些选项才能完成这项工作,最好不要为每个“类图像”类提供两个几乎相同的构造函数?

你想要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 aStreamReader("filepath"); // rvalue

const StreamReader s("filepath");
Image bs; // const lvalue

StreamReader s2("filepath");
Image cs2; // lvalue

如果您想阻止const&amp; 被接受,您可以delete 那个特定的重载,或者将它添加到enable_if_t 子句中:

Image(const StreamReader&amp;) = delete;

(假设类型始终为StreamReader)。

std::enable_if_t&lt;!std::is_const_v&lt;T&gt; &amp;&amp; !std::is_same_v&lt;std::decay_t&lt;T&gt;, Image&gt;&gt;

【讨论】:

谢谢!这似乎差不多了。但我不想通过 const& 而是 &。 (即使是左值流在传递时也会改变其文件位置。)这可能吗? @ChrisB:是的,它接受一切。更新了我的示例。 非常感谢!我可以以某种方式阻止 const& 被接受吗? @ChrisB:当然可以,只需将其添加到enable_if_t 子句中即可。正在更新答案... @ChrisB:不,我试图阻止完美转发构造函数劫持Image(const Image&amp;)Image(Image&amp;&amp;),这可能是隐式生成的。 is_same 正在这样做。

以上是关于C++ 非 const 右值参数解决方法的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 11 中将非 const 左值引用绑定到右值是不是有效?(修改)

C++ 函数透明地采用左值和右值参数

无法调用或分配具有右值引用作为参数的 std::function (Visual C++)

临时变量不能作为非const引用

如何从 const 方法调用非 const 方法?

将数组作为 C++ 中方法的 const 参数传递