Ada*_*ura 4 c++ constructor rvalue-reference c++11
让我们考虑一个简单的类
template< typename T >
class Wrapper {
public:
// Constructors?
private:
T wrapped;
};
Run Code Online (Sandbox Code Playgroud)
应该使用什么构造函数才能有效?
在C++ 0x之前,会有一个构造函数采用以下任一方法:
T const&) - 如果type T为"heavy",T) - 如果type T为"light".确定类型T是"重"还是"轻"并不容易.
可以假设只有内置类型(ints/floats/...)是"轻"的.但这并不完全正确,因为我们自己Wrapper<int>最有可能也应被视为"轻型"类型.
boost::call_traits通过允许类型创建者将类型标记为"轻"(通过提供适当的call_traits专业化),库提供了一些克服此困难的方法.否则它将被视为"沉重".似乎可以接受.
但是C++ 0x使它变得更糟.因为现在你还有rvalue reference(T&&),它允许有效地获取(某些)"重"对象.
因此,你必须选择:
T const&) - 如果类型T是"重"并且不支持移动语义(因为没有任何一个 - 就像大POD一样 - 或者没有写入并且你对它没有影响),T const&)和rvalue reference(T&&) - 如果type T为"heavy"并且支持移动语义,T) - 如果type T是"light"或者它是"重"但支持移动语义(即使复制它也不会使用,否则我们无论如何都要从T const&自己复制......).仍然不容易分辨哪些类型是"重",哪些是"轻"(如前所述).但是现在你也无法判断类型是否T支持移动语义(或者是你?).
一旦你包装了多个值,这就变得更加烦人,因为可能的构造函数重载数量呈指数增长.
这个问题有什么解决方案吗?
我虽然有一些模板构造函数用于转发(完美转发)参数,但我不确定这是否会按预期工作.并且它还允许提供将被转发到T构造函数的不同类型的值.这可能被认为是一个功能,但不是必须的.
相反,由于通用引用,C++ 11使其变得更容易:
template <typename T> struct Wrapper
{
T value;
template <typename U> Wrapper(U && u)
: value(std::forward<U>(u))
{ }
};
Run Code Online (Sandbox Code Playgroud)
作为一个特别好的触摸,你应该添加一个默认的第二个参数,该参数只有在T可构造时才存在U,以免使你的类本身看起来可以从不匹配的类型构造.并使它变得可变:
template <typename ...Args>
Wrapper(Args &&... args,
typename std::enable_if<std::is_constructible<T, Args...>::value, int>::type = 0)
: value(std::forward<Args>(args)...)
{ }
Run Code Online (Sandbox Code Playgroud)
确保#include <utility>为特征forward和#include <type_traits>特征.
| 归档时间: |
|
| 查看次数: |
678 次 |
| 最近记录: |