Reputation: 7844
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
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