*This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.*

`is_*[copy/move]_[constructible/assignable]`

unclear for non-referencable types**Section:** 21.3.5.4 [meta.unary.prop] **Status:** C++14
**Submitter:** Daniel Krügler **Opened:** 2012-10-06 **Last modified:** 2016-01-28

**Priority: **Not Prioritized

**View other** active issues in [meta.unary.prop].

**View all other** issues in [meta.unary.prop].

**View all issues with** C++14 status.

**Discussion:**

The pre-conditions for the type `is_copy_constructible`

allow for template argument types were the language forbids
forming a reference, namely `void`

types and function types that have *cv*-qualifiers or a *ref*-qualifier.

But the current wording in Table 49 defining the predicate condition,

`is_constructible<T, const T&>::value`

is`true`

.

leaves it open whether such argument types would (a) create a well-formed instantiation of the trait template or if so (b) what
the outcome of the trait evaluation would be, as an example consider `std::is_copy_constructible<void>`

.

Current implementations differ, e.g. gcc accepts the instantiation and returns a false result, VS 2012 also accepts the instantiation but returns true.

I would suggest that the wording clarifies that the instantiation would be valid for these types and I also would strongly
prefer the outcome that the trait would always return false for these types. The latter seems rather natural
to me, because there is no way to define a variable of `void`

type or of function type at all, so it would be surprising
to return a positive result for copy or move construction if no other construction could succeed. It is also not
possible to assign to a any of these values (because there is no way to form lvalues of them), so the same argumentation
can be applied to the `is_copy/move_assignable`

traits as well.

To reduce the amount of wording changes and repetitions, I suggest to define the term *referenceable type* in
sub-clause [definitions] or alternatively in the core language to describe types to which references
can be created via a typedef name. This definition corresponds to what the support concept `ReferentType`

intended
to describe during concept time.

In addition, LWG issue 2101 can also take advantage of the definition of a *referenceable type*.

If the proposed resolution for LWG issue 2101 would be accepted, there is an alternative solution possible
with the same effects. Now we would be able to use the now always well-formed instantiation of
`std::add_lvalue_reference`

to modify the current definition of `is_copy_constructible`

to

`is_constructible<T,`

is true.

typename add_lvalue_reference<

typename add_const<T>::type>::type>::value

and similar changes for the other affected traits.

*[2012-10 Portland: Move to Open]*

Referencable-type should be defined as "something that can be bound into a reference" or similar, rather than a list of types where that is true today. We can then provide the list of known types that cannot be bound as examples that do not qualify in a note.

Otherwise we are happy with the wording. AJM to redraft the definition and move to Review.

*[2013-04-18, Bristol]*

**Proposed resolution:**

This wording is relative to N3376.

Add the following new definition to [definitions] as indicated:

**referenceable type**[defns.referenceable]An object type, a function type that does not have

*cv*-qualifiers or a*ref*-qualifier, or a reference type. [*Note*: The term describes a type to which a reference can be created, including reference types. —*end note*]Change Table 49 as indicated:

Table 49 — Type property predicates Template Condition Preconditions `template <class T>`

`struct is_copy_constructible;`

For a referenceable type `T`

, the same result as

`is_constructible<T,`

`const T&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`template <class T>`

`struct is_move_constructible;`

For a referenceable type `T`

, the same result as

`is_constructible<T,`

`T&&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`…`

`template <class T>`

`struct is_copy_assignable;`

For a referenceable type `T`

, the same result as

`is_assignable<T&,`

`const T&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`template <class T>`

`struct is_move_assignable;`

For a referenceable type `T`

, the same result as

`is_assignable<T&,`

`T&&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`…`

`template <class T>`

`struct is_trivially_copy_constructible;`

For a referenceable type `T`

, the same result as

`is_trivially_constructible<T,`

`const T&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`template <class T>`

`struct is_trivially_move_constructible;`

For a referenceable type `T`

, the same result as

`is_trivially_constructible<T,`

`T&&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`…`

`template <class T>`

`struct is_trivially_copy_assignable;`

For a referenceable type `T`

, the same result as

`is_trivially_assignable<T&,`

`const T&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`template <class T>`

`struct is_trivially_move_assignable;`

For a referenceable type `T`

, the same result as

`is_trivially_assignable<T&,`

`T&&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`…`

`template <class T>`

`struct is_nothrow_copy_constructible;`

For a referenceable type `T`

, the same result as

`is_nothrow_constructible<T,`

`const T&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`template <class T>`

`struct is_nothrow_move_constructible;`

For a referenceable type `T`

, the same result as

`is_nothrow_constructible<T,`

`T&&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`…`

`template <class T>`

`struct is_nothrow_copy_assignable;`

For a referenceable type `T`

, the same result as

`is_nothrow_assignable<T&,`

`const T&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.`template <class T>`

`struct is_nothrow_move_assignable;`

For a referenceable type `T`

, the same result as

`is_nothrow_assignable<T&,`

`T&&>::value`

~~is true~~, otherwise false.`T`

shall be a complete type,

(possibly*cv*-qualified)`void`

, or an

array of unknown bound.