relaxxx
relaxxx

Reputation: 7844

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

Given

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

std::is_copy_constructible<Foo>::value is false

Foo has valid copy-constructor: From draft 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.

but is_copy_constructible tests is_constructible_v<T, const T&> (const) according to the standard.

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

Upvotes: 4

Views: 692

Answers (1)

Corristo
Corristo

Reputation: 5520

While this is indeed a valid copy constructor, the is_copy_constructible type-trait is defined to give the same result as is_constructible_v<T, const T&>, because it is intended to correspond to the CopyConstructible concept that is also defined by the standard.

In [utility.arg.requirements]/1 it says

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.

The CopyConstructible concept is defined in Table 24 as

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)

Therefore, since your object is not constructible from a const Foo lvalue, which is one of the requirements of CopyConstructible, it is not regarded as such.

Upvotes: 4

Related Questions