为什么CopyConstructable类型也必须是MoveConstructable

Why does a CopyConstructible type also have to be MoveConstructible?

本文关键字:MoveConstructable CopyConstructable 类型 为什么      更新时间:2023-10-16

如cppreference中所述,类型TCopyConstructible的一个要求是它也是MoveConstructible

STL CopyConstructable概念草案包含:

template <class T>
concept CopyConstructible =
std::MoveConstructible<T> &&
std::Constructible<T, T&> && std::ConvertibleTo<T&, T> &&
std::Constructible<T, const T&> && std::ConvertibleTo<const T&, T> &&
std::Constructible<T, const T> && std::ConvertibleTo<const T, T>;

,支持命名的需求语句。给定上述定义,一种类型类似于:

struct HaveCopy {
HaveCopy(const HaveCopy&)  = default;
HaveCopy(HaveCopy&&)       = delete;
HaveCopy& operator= (const HaveCopy&)  = default;
HaveCopy& operator= (HaveCopy&&)       = delete;
};

未通过简单测试:

static_assert(std::CopyConstructible<HaveCopy>);

而它通过了旧的:

static_assert(std::is_copy_constructible<HaveCopy>::value);

所以,问题是为什么?标准委员会在这件事上的意图是什么?HaveCopy不是可移动的,但在我看来,它几乎是可复制的,std::is_copy_constructible<>同意我的观点。

可复制概念也继承了相同的行为,即:

template <class T>
concept Copyable =
std::CopyConstructible<T> &&
std::Movable<T> &&
std::Assignable<T&, const T&>;

因此测试:

static_assert(std::Copyable<HaveCopy>);

也将失败。这一次失败加倍。CopyConstrucible<>Movable<>都不同意HaveCopy是可复制的。

这里的讨论在某种程度上是相似的,但没有回答为什么。为什么我们需要这种行为?这种检查是否排除了有效的可复制构造类型,或者HaveCopy根本不可复制构造?如果最后一个是真的,我觉得很奇怪。

有什么想法吗?

是的,CopyConstructible的概念与类型特征std::is_copy_constructible大不相同。您关注的是move构造函数,但也有许多其他情况需要考虑。你认为这种类型应该是CopyConstructable吗?
struct A {
A(A&) = delete;
A(A const&);
};

这个怎么样?

struct B {
explicit B(B const&);
};

关键是,你可以编写各种各样的构造函数组合。这并不意味着它们都有意义或值得支持。拥有一个带有复制构造函数但删除了移动构造函数的类型是没有意义的。

概念不仅仅是进行语法检查,它还涉及强制执行语义需求,以推动有意义的类型——最终更容易进行编码。如果您只需检查is_copy_constructible,那么您所要做的就是从const lvalue显式地构造类型。编写T x = y;,即使yconst T,也已经超出了该范围!这可能就是复制可构造性的字面意思,但它的意义远不如更广泛的"我可以从T构造T"——这更接近于我们在考虑复制时的实际想法。这就是CopyConstructible给我们的概念

当你浏览这个库时,还有其他概念需要比直接翻译它们的名字更高的要求(语法和语义)。EqualityComparableWith<T,U>不仅检查我是否可以写t == u,还检查u == tt != uu != tStrictTotallyOrdered不仅检查排序运算符,它还检查==。拥有一个有凝聚力的整体很重要。

相关文章:
  • 没有找到相关文章