为什么 class with non-const copy constructor 不被视为可复制构造?

Why is class with non-const copy constructor not treated as copy constructible?

给定

struct Foo 
{
    Foo(Foo&) {} 
};

std::is_copy_constructible<Foo>::valuefalse

Foo 具有有效的复制构造函数:来自 n4659 草案:

15.8.1 Copy/move constructors [class.copy.ctor]
1
A non-template constructor for class X is a copy constructor if its first parameter is of type X& , const X& ,
volatile X& or const volatile X& , and either there are no other parameters or else all other parameters
have default arguments (11.3.6). [Example: X::X(const X&) and X::X(X&,int=1) are copy constructors.

is_copy_constructible 根据标准测试 is_constructible_v<T, const T&> (const)。

为什么 class 使用非常量复制构造函数不被视为可复制构造?

虽然这确实是一个有效的复制构造函数,但 is_copy_constructible 类型特征被定义为给出与 is_constructible_v<T, const T&> 相同的结果,因为它旨在对应于 CopyConstructible标准也定义了这个概念。

[utility.arg.requirements]/1中说

The template definitions in the C++ standard library refer to various named requirements whose details are set out in Tables 20–27. In these tables, T is an object or reference type to be supplied by a C++ program instantiating a template;[...] and v is an lvalue of type (possibly const) T or an rvalue of type const T.

CopyConstructible 概念在Table 24 中定义为

Table 24 — CopyConstructible requirements (in addition to MoveConstructible)
Expression     Post-condition
T u = v;           the value of v is unchanged and is equivalent to u
T(v)                 the value of v is unchanged and is equivalent to T(v)

因此,由于您的对象不能从 const Foo 左值构造,这是 CopyConstructible 的要求之一,因此不被视为如此。