【问题标题】:combining two constructors that copy and move结合两个复制和移动的构造函数
【发布时间】:2011-11-15 08:25:03
【问题描述】:

目前,我的一个玩具类模板有两个看起来非常相似的构造函数:

optional(const T& x)
{
    construct(x);
}

optional(T&& x)
{
    construct(std::move(x));
}

我可以将它们组合成一个构造函数模板,还是会以某种方式改变语义?

template<typename U>
optional(U&& x)
{
    construct(std::forward<U>(x));
}

【问题讨论】:

  • construct的实际肉是什么?
  • @Alf: 丑陋的新东西放置在对齐的存储上 :)

标签: c++ templates c++11 move-semantics perfect-forwarding


【解决方案1】:

模板化的构造函数永远不会(被编译器认为是)复制构造函数,抱歉。

【讨论】:

  • 呃,optional(const T&amp;) 甚至都不是复制构造函数,我在想什么?已编辑
  • @Fred:在那种情况下,考虑使用 C++11 构造函数转发?如果它是由编译器实现的。我不知道哪些编译器支持它,如果有的话。或者,如果不支持,您可以使用人工基类。将构造函数调用转发到基类。
  • 哦,construct 不是构造函数,它是成员函数模板。
  • IBM XL 编译器实现了delegating constructors。但是,我不知道有谁真正使用过那个编译器:-)
  • 虽然有了完美的转发构造函数模板,你会遇到optional&lt;int&gt; x, y(x); 的问题。这将调用完美转发构造函数模板来进行复制,这可能不是您想要的。所以如果remove_reference&lt;U&gt;::typecv optional&lt;T&gt;,你需要一些SFINAE 来禁用它
【解决方案2】:

它改变了诸如std::is_constructiblestd::is_convertible 等特征与optional 交互的方式。例如给出:

class A {};

int main()
{
    std::cout << std::is_constructible<optional<A>, int>::value << '\n';
};

您的原始代码会打印出来:

0

但是你的新代码会打印出来:

1

如果这是不可取的,并且您仍想使用新代码,您可以enable_ifU 限制为可接受的类型。

我看到的唯一其他可能的问题是T 是否可以是引用类型(例如int&amp;)。在这种情况下,您的原始代码的第二个构造函数看起来很可疑,因为它会传入一个右值,并且您可能正在尝试将该右值绑定到一个非 const 左值引用(无法确定)。如果T 永远不能是引用类型,则无需担心。

【讨论】:

    【解决方案3】:

    哦,construct 不是构造函数,它是成员函数模板。

    那么可能语义不同。您的原始重载集将左值引用传递给 const 或将右值引用传递给非 const。模板版本也可以将左值引用传递给 non-const。 (我忽略了对 const 的右值引用。)

    尽管construct 很可能被声明为接受U&amp;&amp;(否则您之前移动T 的重载将不起作用)并且在这种情况下应该处理非const lvalues,或者声明接受U const&amp;,在这种情况下它是无害的。

    【讨论】:

      【解决方案4】:

      假设您至少定义了construct(const T&amp; x) 并且可能添加了construct(T&amp;&amp; x),并且您的U 类型的对象可以转换为T 类型的对象,我认为您应该没问题...

      1. U 类型的常量左值引用将绑定到 construct(const T&amp; x)
      2. U 类型的非常量左值引用将绑定到construct(const T&amp; x)
      3. 如果未定义右值参考版本,U 类型的临时右值将绑定到 construct(T&amp;&amp; x)construct(const T&amp; x)
      4. U 类型的常量 r 值引用将绑定到 construct(const T&amp; x)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-28
        • 2023-03-20
        • 2018-09-23
        • 2013-11-05
        • 2015-08-14
        • 1970-01-01
        • 1970-01-01
        • 2023-03-11
        相关资源
        最近更新 更多