hoo*_*oo2 10 c++ c++-concepts c++20
如cppreference中所述,类型T为CopyConstructible的要求是它也是MoveConstructible.
STL CopyConstructible概念的草案包含:
Run Code Online (Sandbox Code Playgroud)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;
};
Run Code Online (Sandbox Code Playgroud)
没有简单的测试:
static_assert(std::CopyConstructible<HaveCopy>);
Run Code Online (Sandbox Code Playgroud)
而它通过了旧的:
static_assert(std::is_copy_constructible<HaveCopy>::value);
Run Code Online (Sandbox Code Playgroud)
那么,问题是为什么呢?标准委员会对此事的意图是什么?HaveCopy不是可构造的,但在我看来几乎是可复制的,并且std::is_copy_constructible<>与我一致.
Copyable概念也继承了相同的行为,即:
Run Code Online (Sandbox Code Playgroud)template <class T> concept Copyable = std::CopyConstructible<T> && std::Movable<T> && std::Assignable<T&, const T&>;
所以测试:
static_assert(std::Copyable<HaveCopy>);
Run Code Online (Sandbox Code Playgroud)
也会失败.这次失败加倍.双方CopyConstrucible<>并Movable<>同意该HaveCopy是可复制.
这里的讨论有点类似,但没有回答原因.为什么我们需要这种行为?这种检查是否排除了有效的可复制构造类型,或者HaveCopy是否完全不可复制?如果确实如此,那对我来说似乎很奇怪.
有什么想法吗?
是的,CopyConstructible这个概念与类型特征完全不同std::is_copy_constructible.你专注于移动构造函数,但还有许多其他情况需要考虑.你认为这种类型应该是CopyConstructible吗?
struct A {
A(A&) = delete;
A(A const&);
};
Run Code Online (Sandbox Code Playgroud)
这个怎么样?
struct B {
explicit B(B const&);
};
Run Code Online (Sandbox Code Playgroud)
关键是,你可以编写各种各样的构造函数组合.这并不意味着他们都有意义或值得支持.具有复制构造函数但删除的移动构造函数的类型根本没有意义.
概念不只是进行语法检查,它还涉及强制语义需求以推送有意义的类型 - 这最终会更容易编码.如果您只是检查is_copy_constructible,那么您允许自己做的就是从const左值显式构造您的类型.写作T x = y;,即使y是一个const T,已经超出了这个范围!这可能是字面上拷贝构造的手段,但它比少了很多有意义的更广泛的"我可以构建一个T从T" -这是很多更接近真正的我们认为,当我们考虑复制.这就是这个概念CopyConstructible给我们带来的.
当您浏览库时,还有其他概念需要更多(语法和语义),而不是直接翻译它们的名称.EqualityComparableWith<T,U>不只是检查我可以写t == u,而且u == t,t != u和u != t也.StrictTotallyOrdered不只是检查订货的运营商,它也检查==.拥有一个有凝聚力的整体很重要.