【问题标题】:is_copy_constructible typetrait gives wrong answeris_copy_constructible typetrait 给出了错误的答案
【发布时间】:2021-11-05 02:24:11
【问题描述】:

在下面的代码中,is_copy_constructible_v 返回 true,但 MainClass 的复制构造函数被标记为已删除。

试图调用复制构造函数是一个编译错误。
is_copy_constructible_v怎么看不到呢?

class BaseClass {};

class MainClass : public BaseClass {
public:
    MainClass(MainClass&) = delete;

    MainClass(const BaseClass& rhs)
    {
    }
};

int main()
{
    MainClass first{{}};

    //This line will not compile because MainClass::MainClass(MainClass&) is a deleted function
    //MainClass second{first};

    auto mainclass_is_constructible = std::is_copy_constructible_v<MainClass>;

    //This assert fails because is_copy_constructible_v returns true
    static_assert((std::is_copy_constructible_v<MainClass>) == 0);
}

这是通过检查给定类是否可复制/可移动的单元测试发现的。
它们可以正常工作,但在实际代码中添加了 MainClass(const BaseClass&amp; rhs) 的等效项后就不行了。

如果我们有MainClass(const BaseClass&amp; rhs, int value),那么is_copy_constructible_v 将起作用。

如果我们也删除移动 ctor/assignment,给定 std::vector&lt;MainClass&gt; 会发生什么?向量会不会利用is_copy_constructible_v来检测如何操作最好,得到错误的答案?

非常感谢

【问题讨论】:

  • 你没有删除MainClass(MainClass const&amp;)。这样就可以使用有效的复制构造函数了。
  • 它是可复制的。您可以通过执行以下操作进行验证:MainClass second{static_cast&lt;const MainClass&amp;&gt;(first)}; 因此它调用复制构造函数而不是传递引用构造函数。即使这样做:const auto&amp; temp = first; MainClass second{temp}; 也可以。
  • 确实应该是MainClass(const MainClass&amp;)。谢谢

标签: c++ typetraits


【解决方案1】:

MainClass 有一个 MainClass::MainClass(const BaseClass&amp; rhs),这使得从 const 左值构造 MainClass 成为可能,例如

const MainClass first{{}};

// This line will compile because MainClass::MainClass(const BaseClass& rhs) is usable
// a MainClass could be bound to const BaseClass&
MainClass second{first};

std::is_copy_constructible 执行检查为:

提供一个等于std::is_constructible&lt;T, const T&amp;&gt;::value的成员常量值。

请注意,它正在检查 T 是否可以从 const T&amp; 构造,然后为 MainClass 生成 true

如果将复制构造函数声明为:

MainClass(const MainClass&) = delete;

你会得到结果false

给出std::vector&lt;MainClass&gt;会发生什么

它将使用MainClass::MainClass(const BaseClass&amp; rhs)(用于push_back 或重新分配等)。如果不是您所期望的,您必须重新考虑设计。

【讨论】:

  • 非常感谢,这个问题是由于未能通知MainClass(MainClass&amp;) = delete; 中缺少的const 而现在MainClass(const MainClass&amp;) = delete; 它当然可以工作了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多