C++ 非 const 右值参数解决方法
C++ non const rvalue parameter workaround
我有一些提供基本 IO 的 Stream classes。
我希望能够编写这样的代码:
Image img = Image(StreamReader("filepath"));
不幸的是,根据标准,将右值引用绑定到非 const 左值引用似乎是非法的,例如 Image ctor 的参数。
我不能将参数设为 const 引用,因为 Streams 需要更新它们的状态,例如当前流位置。
使这些 Stream 属性可变或对它们进行常量转换对我来说似乎是糟糕的设计,因为这些状态对用户有明显的影响。
我有什么选择来完成这项工作,最好不要为每个 'Image-like' class 使用两个几乎相同的构造函数?
提前致谢。
What options do I have to make this work, preferrably without having two nearly identical constructors for every 'Image-like' class?
你想要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>>
我有一些提供基本 IO 的 Stream classes。 我希望能够编写这样的代码:
Image img = Image(StreamReader("filepath"));
不幸的是,根据标准,将右值引用绑定到非 const 左值引用似乎是非法的,例如 Image ctor 的参数。
我不能将参数设为 const 引用,因为 Streams 需要更新它们的状态,例如当前流位置。
使这些 Stream 属性可变或对它们进行常量转换对我来说似乎是糟糕的设计,因为这些状态对用户有明显的影响。
我有什么选择来完成这项工作,最好不要为每个 'Image-like' class 使用两个几乎相同的构造函数?
提前致谢。
What options do I have to make this work, preferrably without having two nearly identical constructors for every 'Image-like' class?
你想要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>>