is_constructible<T[], T...>
may be misleading in C++20Section: 21.3.5.4 [meta.unary.prop] Status: LEWG Submitter: Jonathan Wakely Opened: 2020-10-01 Last modified: 2020-10-01
Priority: Not Prioritized
View other active issues in [meta.unary.prop].
View all other issues in [meta.unary.prop].
View all issues with LEWG status.
Discussion:
According to the current wording,
std::is_constructible<int[], int>
should be true, because the preconditions are met
(all types are complete types or unbounded arrays)
and the variable definition is well-formed since C++20:
using T = int[]; T t(declval<int>()); // equiv. to int t[] = {1};
However, this doesn't construct an object of type int[]
because it deduces the array bound from the initializers,
and so constructs int[1]
, which is not the type being asked about.
It seems more logical for the trait to give a false result
for an unbounded array, because it's an incomplete type,
and no int[]
can ever be constructed.
On the reflector Tim Song noted:
On the other hand, the result is something to which an int(&)[]
can be bound directly thanks to another C++20 change,
so a lot of things might Just Work (for some definition of "Work")
despite the type difference.
This seems to me a reasonable rationale for
is_constructible<int(&&)[], int>
to be true (which it is today),
but not for int[]
.
Peter Dimov replied:
Placement new, which is often the way to construct we're interested in,
is not going to work even for T[2]
.
For example:
using T2 = int[2]; T2 x; new(x) T2(1, 2); // ill-formed
We need to decide what behaviour we want here.
Do we just want is_constructible
to reflect the T(declval<Args...>);
construct
as currently specified in 21.3.5.4 [meta.unary.prop] p8,
or do we want to give a more useful/meaningful answer here?
Should we revisit 21.3.5.4 [meta.unary.prop] p8
in the light of parenthesized aggregate init,
so that is_constructible<T[], T>
and is_constructible<T[1], T>
are false?
There may be some interaction with LWG 3436.
Proposed resolution: