C++ 为什么可复制的类型也必须是可移动的?

C++ 为什么可复制的类型也必须是可移动的?,c++,c++-concepts,c++20,C++,C++ Concepts,C++20,如中所述,类型T要可复制的要求是它也要可移动 STL概念草案包括: 未能通过简单测试: static_assert(std::CopyConstructible<HaveCopy>); static_断言(std::CopyConstructible); 鉴于它超越了旧的: static_assert(std::is_copy_constructible<HaveCopy>::value); static\u assert(std::is\u copy\u cons

如中所述,类型T可复制的要求是它也要可移动

STL概念草案包括:

未能通过简单测试:

static_assert(std::CopyConstructible<HaveCopy>);
static_断言(std::CopyConstructible);
鉴于它超越了旧的:

static_assert(std::is_copy_constructible<HaveCopy>::value);
static\u assert(std::is\u copy\u constructible::value);
所以,问题是为什么?标准委员会对此有何打算?HaveCopy不是move-constructible,但在我看来,它几乎是copy-constructible,而且
std::is_-copy_-constructible
同意我的观点

该概念也继承了相同的行为,即:

模板
概念可复制=
std::可复制&&
std::可移动&&
std::可分配;
因此,测试:

static_assert(std::Copyable<HaveCopy>);
static_断言(std::Copyable);
也会失败。这一次的失败是双倍的。
CopyConstrucible
Movable
都不同意HaveCopy是可复制的

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


有什么想法吗?

是的,
CopyConstructible
这个概念与类型trait
std::is\u copy\u constructible
截然不同。你把注意力放在移动构造函数上,但是还有很多其他的情况需要考虑。你认为这种类型应该是可复制的吗

struct A {
    A(A&) = delete;
    A(A const&);
};
这个怎么样

struct B {
    explicit B(B const&);
};
关键是,您可以编写各种各样的构造函数组合。这并不意味着它们都有意义或值得支持。使用具有复制构造函数但已删除的移动构造函数的类型根本没有意义

概念不仅仅是进行语法检查,它还涉及强制执行语义需求以推动有意义的类型——最终更容易进行编码。如果您只需检查
是否可复制\u可构造
,您所能做的就是从常量左值显式构造类型。写入
tx=y,即使
y
const T
,也已超出该范围!这可能是字面上可复制的方法,但它比“我可以从代码< t>代码>中构造一个<代码> t>代码>的意义少得多——这与我们考虑复制时的实际情况更为接近。这就是
CopyConstructible
的概念给我们的


当你浏览图书馆时,还有其他一些概念需要更多的(语法和语义上的)翻译,而不是直接翻译它们的名字。不只是检查我是否可以写
t==u
,还可以写
u==t
t!=u
,和
u!=t
。不仅检查排序运算符,它还检查
=
。拥有一个有凝聚力的整体是很重要的

Jonathan Wakely在链接线程中的回答不也回答了为什么部分吗?“MoveConstructible不需要移动任何东西,只需要从右值进行构造是可能的,所有CopyConstructible类型都可以从右值进行构造(即使它们可能进行深度复制而不是移动)。”我的理解是,当某个东西被移动时,你不应该关心它是否被移动或复制,因此,如果某个东西是可复制的,那么它会自动地是可移动的,你无法分辨其区别,而且这不是一个额外的要求。我同意lubr,并将此问题标记为重复问题,你认为哪一部分没有被链接的答案回答?很可能是我不太理解。。。Wakely的回答是“我们试图避免反常类型[and/so],?我们还需要移动构造函数,因为有人可能会使用它进行复制?”。为什么我们要问可移动的概念?为什么在这样做的时候我们把HaveCopy排除在CopyConstructible之外?这就像问“为什么所有可被4整除的数字都必须被2整除?”。由于
T&
const T&
的“隐式转换”,任何可以从
T&
实例化的
T&
都可以从
T&
实例化。“可以从
T&
实例化”是moveconstructable的定义,所以它的全部内容都是关于措辞的?如果是的话,请考虑我对概念措辞的直觉反应。首先引用你(非常好)对CopyConstructible的回答:“我可以从一个T构造一个T”。这就是可构造的目的吗?第二copyconstructable是“我可以从T复制T”会更好吗?@hoo2:像这样的需求更多的是关于表达式的生存能力,而不是语义效果(尽管它们也有)。考虑<代码> t=某某;
T=func_返回_T()。用户是否真正关心它是否是“副本”?或者他们只是关心他们有一个
T
,并且能够从中构造另一个
T
。@hoo2:是的,用户关心类型是否是仅移动的,因此
T=some\T不编译。但是为什么用户需要
T=func_返回_T()不编译?如果可以从左值创建实例,为什么不能从右值创建实例?可复制但不可移动的类型打破了这些操作的基本概念。@hoo2“允许移动但不可复制”是一个非常合理的语义,它不缺少重要的用例。“允许复制但不能移动”是。。。从字面上说,这是一个可以写的东西。这些并不完全平等。@tangy那句话在上面写着“(直到C++11)”。
static_assert(std::Copyable<HaveCopy>);
struct A {
    A(A&) = delete;
    A(A const&);
};
struct B {
    explicit B(B const&);
};