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.
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&&...> is true.
emplace (initializer_list form) has a SFINAE condition:
Remarks: […] unless is_constructible_v<T, initializer_list<U>&, Args&&...> is true.
In 22.7.4.4 [any.modifiers]: emplace (normal form) has a Requires that the construction works:
Requires: is_constructible_v<T, Args...> is true.
emplace (initializer_list form) has a SFINAE condition:
Remarks: […] unless is_constructible_v<T, initializer_list<U>&, Args...> is true.
In 22.6.3.5 [variant.mod]: emplace (T, normal form) has a SFINAE condition:
Remarks: […] unless is_constructible_v<T, Args...> is true, and T occurs exactly once in Types....
emplace (Idx, normal form) has a both a Requires and a SFINAE condition:
Requires: I < sizeof...(Types)
Remarks: […] unless is_constructible_v<T, Args...> is true, and T occurs exactly once in Types....
emplace (T, initializer_list form) has a SFINAE condition:
Remarks: […] unless is_constructible_v<T, initializer_list<U>&, Args...> is true, and T occurs exactly once in Types....
emplace (Idx, initializer_list form) has a both a Requires and a SFINAE condition:
Requires: I < sizeof...(Types)
Remarks: […] unless is_constructible_v<T, Args...> is true, and T occurs exactly once in Types....
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_lists, 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, 2754 and 2756 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 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-
[…]MandatesConstraints: is_constructible_v<T, Args...> is true.template<class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);-35- Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.
[…]
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...> is true, and T occurs exactly once in Types.
[…]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...> is true, and T occurs exactly once in Types.
[…]template<size_t I, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);-6- Constraints: is_constructible_v<TI, Args...> is true and I < sizeof...(Types) is true. […]
-5- Mandates: I < sizeof...(Types).template<size_t I, class U, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args);-13- Constraints: is_constructible_v<TI, initializer_list<U>&, Args...> is true and I < sizeof...(Types) is true. […]
-12- Mandates: I < sizeof...(Types).