This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
2746. Inconsistency between requirements foremplace
between optional
and variant
Section: 22.5.3.4 [optional.assign], 22.6.3.5 [variant.mod], 22.7.4.4 [any.modifiers] Status: New Submitter: Richard Smith Opened: 2016-07-13 Last modified: 2020-05-10
Priority: 3
View all issues with New status.
Discussion:
Referring to N4604:
In [optional.object.assign]: emplace
(normal form) has a Requires that the construction works.
Requires:
is_constructible_v<T, Args&&...>
istrue
.
emplace
(initializer_list
form) has a SFINAE condition:
Remarks: […] unless
is_constructible_v<T, initializer_list<U>&, Args&&...>
istrue
.
In 22.7.4.4 [any.modifiers]: emplace
(normal form) has a Requires that the construction works:
Requires:
is_constructible_v<T, Args...>
istrue
.
emplace
(initializer_list
form) has a SFINAE condition:
Remarks: […] unless
is_constructible_v<T, initializer_list<U>&, Args...>
istrue
.
In 22.6.3.5 [variant.mod]: emplace
(T
, normal form) has a SFINAE condition:
Remarks: […] unless
is_constructible_v<T, Args...>
istrue
, andT
occurs exactly once inTypes...
.
emplace
(Idx, normal form) has a both a Requires and a SFINAE condition:
Requires:
Remarks: […] unlessI < sizeof...(Types)
is_constructible_v<T, Args...>
istrue
, andT
occurs exactly once inTypes...
.
emplace
(T
, initializer_list
form) has a SFINAE condition:
Remarks: […] unless
is_constructible_v<T, initializer_list<U>&, Args...>
istrue
, andT
occurs exactly once inTypes...
.
emplace
(Idx, initializer_list
form) has a both a Requires and a SFINAE condition:
Requires:
Remarks: […] unlessI < sizeof...(Types)
is_constructible_v<T, Args...>
is true, andT
occurs exactly once inTypes...
.
Why the inconsistency? Should all the cases have a SFINAE requirement?
I see that variant has an additional requirement (T
occurs exactly once in Types...
), but that only agues that it must be a SFINAE condition — doesn't say that the other cases (any/variant) should not. map
/multimap
/unordered_map
/unordered_multimap
have SFINAE'd versions of emplace
that don't take initializer_list
s, but they don't have any emplace
versions that take ILs. Suggested resolution: Add SFINAE requirements to optional::emplace(Args&&... args)
and any::emplace(Args&&... args);
[2016-08 Chicago]
During issue prioritization, people suggested that this might apply to any
as well.
Ville notes that 2746(i), 2754(i) and 2756(i) all go together.
[2020-05-10; Daniel comments and provides wording]
The inconsistency between the two any::emplace
overloads have been removed by resolving LWG 2754(i) to use Constraints: elements. The last Mandating paper (P1460R1), adopted in Prague, changed the Requires: elements for variant::emplace
, "I < sizeof...(Types)
" to Mandates:, but that paper was focused on fixing inappropriate preconditions, not searching for consistency here. Given that the in_place_index_t
constructors of variant
uses SFINAE-conditions for this form of static precondition violation, I recommend that its emplace
functions use the same style, which would bring them also in consistency with their corresponding type-based emplace
forms that are Mandates:-free but delegate to the index-based forms.
Proposed resolution:
This wording is relative to N4861.
Modify 22.5.3.4 [optional.assign], as indicated:
template<class... Args> T& emplace(Args&&... args);-29- Mandates Constraints:
[…]is_constructible_v<T, Args...>
istrue
.template<class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);-35- Constraints:
[…]is_constructible_v<T, initializer_list<U>&, Args...>
istrue
.
Modify 22.6.3.5 [variant.mod], as indicated:
template<class T, class... Args> T& emplace(Args&&... args);-1- Constraints:
[…]is_constructible_v<T, Args...>
istrue
, andT
occurs exactly once inTypes
.template<class T, class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);-3- Constraints:
[…]is_constructible_v<T, initializer_list<U>&, Args...>
istrue
, andT
occurs exactly once inTypes
.template<size_t I, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);-5- Mandates:
-6- Constraints:I < sizeof...(Types)
.is_constructible_v<TI, Args...>
istrue
andI < sizeof...(Types)
istrue
. […]template<size_t I, class U, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args);-12- Mandates:
-13- Constraints:I < sizeof...(Types)
.is_constructible_v<TI, initializer_list<U>&, Args...>
istrue
andI < sizeof...(Types)
istrue
. […]
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4