如cppreference中所述,类型 T 必须为 CopyConstructible 的要求是它也必须为 MoveConstructible 。 / p>
STL CopyConstructible概念的草案包含:
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<>
同意我的看法。
Copyable概念也继承了相同的行为,即:
template <class T> concept Copyable = std::CopyConstructible<T> && std::Movable<T> && std::Assignable<T&, const T&>;
所以测试:
static_assert(std::Copyable<HaveCopy>);
也会失败。这次故障增加了一倍。 CopyConstrucible<>
和Movable<>
都不同意HaveCopy是可复制的。
讨论here在某种程度上相似,但是没有回答为什么。为什么我们需要这种行为?这种检查是否排除有效的副本可构造类型,或者HaveCopy根本不是副本可构造类型?如果是真的,最后一个似乎对我来说很奇怪。
有什么想法吗?
答案 0 :(得分:7)
是的,CopyConstructible
的概念与类型特征std::is_copy_constructible
完全不同。您将重点放在move构造函数上,但是还有许多其他情况需要考虑。您认为这种类型应该是CopyConstructible吗?
struct A {
A(A&) = delete;
A(A const&);
};
这个怎么样?
struct B {
explicit B(B const&);
};
要点是,您可以编写各种构造函数组合。这并不意味着它们都有意义或值得支持。具有复制构造函数但删除了move构造函数的类型根本没有意义。
概念不仅涉及语法检查,还涉及强制语义要求以推送有意义的类型-最终使编码变得更容易。如果仅检查is_copy_constructible
,您要做的就是从const lvalue显式构造 。即使T x = y;
是y
,写const T
也已经超出了范围!从字面上看,这可能是可构造副本的含义,但是它比更广泛的“我可以从T
来构造T
”的意义要小得多-这与我们实际想到的内容非常接近考虑复制。这就是CopyConstructible
这个概念给我们的。
当您浏览库时,还有其他一些概念(在语法上和语义上)需要比其名称的直接翻译所暗示的更多的内容。 EqualityComparableWith<T,U>
不仅检查我可以写t == u
,而且还检查u == t
,t != u
和u != t
。 StrictTotallyOrdered
不仅检查订购运算符,还 检查==
。具有凝聚力的整体很重要。