This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.
tuple
or optional
from {aggregate-member-value}
Section: 22.4.4.2 [tuple.cnstr], 22.5.3.2 [optional.ctor] Status: NAD Submitter: Ville Voutilainen Opened: 2020-05-01 Last modified: 2020-11-09
Priority: 2
View other active issues in [tuple.cnstr].
View all other issues in [tuple.cnstr].
View all issues with NAD status.
Discussion:
For reference, see this gcc bug report.
Constructing atuple
or optional
from an element value of an aggregate
is broken in C++20. tuple<c> t({val});
and optional<c> t({val});
invoked a non-forwarding constructor before, but now the perfect-forwarding converting
constructors are a match, because the element is constructible from {val}
. But
it's not convertible, so overload resolution chooses the explicit constructor, and the
initialization fails.
Tim Song explains the overload resolution in
this reflector discussion.
Now that we understand that C++17 called the non-forwarding conversion constructor,
and C++20 tries to use the forwarding conversion constructor, we have the solution.
SFINAE away the forwarding conversion constructor when it would convert an aggregate.
This also means that tuple<c> t(0);
won't work, which is unfortunate
because tuple<c>/optional<c>
no longer mirrors what c
can do.
That's okay; in this LWG issue, we first restore feature parity with C++17, and later,
as an extension, enable such initializations so that tuple
/optional
mirrors what c
can do in C++20.
The proposed wording below has been implemented and tested.
[2020-05-09; Reflector prioritization]
Set priority to 2 after reflector discussions.
[2020-06-11; LWG Telecon: Status changed: New → LEWG.]
Ask LEWG if it's desirable to make ({val})
work again.
Tomasz would prefer it to be explicit e.g. via std::in_place
.
[2020-06-23; LEWG Telecon]
POLL: Make ({val})
work again, at the risk of non-transparency of tuple constructors and further complicating
the tuple and optional overload set.
SF F N A SA 0 5 6 9 0
No consensus for change. Close as Not a defect.
[2020-11-09 Status changed: Tentatively NAD → NAD.]
Proposed resolution:
This wording is relative to N4861.
Modify 22.4.4.2 [tuple.cnstr] as indicated:
template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&... u);-11- Constraints:
sizeof...(Types)
equalssizeof...(UTypes)
andsizeof...(Types) ≥ 1
andis_constructible_v<Ti, Ui>
istrue
for alli
andconjunction_v<is_aggregate<remove_reference_t<Ti>>, negation<is_same<remove_reference_t<Ti>, remove_reference_t<Ui>>>>
isfalse
for alli
.
Modify 22.5.3.2 [optional.ctor] as indicated:
template<class U = T> constexpr explicit(see below) optional(U&& v);-22- Constraints:
is_constructible_v<T, U>
istrue
,is_same_v<remove_cvref_t<U>, in_place_t>
isfalse
,andis_same_v<remove_cvref_t<U>, optional>
isfalse
, andconjunction_v<is_aggregate<T>, negation<is_same<T, remove_reference_t<U>>>>
isfalse
.