Created on 2025-08-20.00:00:00 last changed 7 days ago
Proposed resolution:
This wording is relative to N5014.
Modify [indirect.ctor] as indicated:
template<class U = T> constexpr explicit indirect(U&& u);-17- Constraints:
(17.1) — is_same_v<remove_cvref_t<U>, indirect> is `false`,
(17.2) — is_same_v<remove_cvref_t<U>, in_place_t> is `false`, and
(17.3) — is_constructible_v<T, U> is `true`, and(17.4) — is_default_constructible_v<Allocator> is `true`.
-?- Mandates: is_constructible_v<T, U> is `true`.
-18- Effects: […]template<class U = T> constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u);-19- Constraints:
(19.1) — is_same_v<remove_cvref_t<U>, indirect> is `false`, and
(19.2) — is_same_v<remove_cvref_t<U>, in_place_t> is `false`.
, and
(19.3) — is_constructible_v<T, U> is `true`-?- Mandates: is_constructible_v<T, U> is `true`.
-20- Effects: […]template<class... Us> constexpr explicit indirect(in_place_t, Us&&... us);-21- Constraints:
(21.1) — is_constructible_v<T, Us...> is `true`, and
(21.2) —is_default_constructible_v<Allocator> is `true`.-?- Mandates: is_constructible_v<T, Us...> is `true`.
-22- Effects: […]template<class... Us> constexpr explicit indirect(allocator_arg_t, const Allocator& a, in_place_t, Us&& ...us);-23-
-24- Effects: […]ConstraintsMandates: is_constructible_v<T, Us...> is `true`template<class I, class... Us> constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us);-25- Constraints:
(25.1) — is_constructible_v<T, initializer_list<I>&, Us...> is `true`, and
(25.2) —is_default_constructible_v<Allocator> is `true`.-?- Mandates: is_constructible_v<T, initializer_list<I>&, Us...> is `true`.
-26- Effects: […]template<class I, class... Us> constexpr explicit indirect(allocator_arg_t, const Allocator& a, in_place_t, initializer_list<I> ilist, Us&&... us);-27-
-28- Effects: […]ConstraintsMandates: is_constructible_v<T, initializer_list<I>&, Us...> is `true`
Modify [polymorphic.ctor] as indicated:
template<class U = T> constexpr explicit polymorphic(U&& u);-12- Constraints: Where `UU` is remove_cvref_t<U>,
(12.1) — is_same_v<UU, polymorphic> is `false`,
(12.2) — derived_from<UU, T> is `true`,(12.3) — is_constructible_v<UU, U> is `true`,
(12.4) — is_copy_constructible_v<UU> is `true`,
(12.5) — `UU` is not a specialization of `in_place_type_t`, and
(12.6) — is_default_constructible_v<Allocator> is `true`.
-?- Mandates: derived_from<UU, T> is `true`.
-13- Effects: […]template<class U = T> constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, U&& u);-14- Constraints: Where `UU` is remove_cvref_t<U>,
(14.1) — is_same_v<UU, polymorphic> is `false`,
(14.2) — derived_from<UU, T> is `true`,(14.3) — is_constructible_v<UU, U> is `true`,
(14.4) — is_copy_constructible_v<UU> is `true`, and
(14.5) — `UU` is not a specialization of `in_place_type_t`.
-?- Mandates: derived_from<UU, T> is `true`.
-15- Effects: […]template<class U, class... Ts> constexpr explicit polymorphic(in_place_type_t<U>, Ts&&... ts);-16- Constraints:
(16.1) — is_same_v<remove_cvref_t<U>, U> is `true`,
(16.2) — derived_from<U, T> is `true`,(16.3) — is_constructible_v<U, Ts> is `true`,
(16.4) — is_copy_constructible_v<U> is `true`, and
(16.5) — is_default_constructible_v<Allocator> is `true`.
-?- Mandates: derived_from<U, T> is `true`.
-17- Effects: […]template<class U, class... Ts> constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, in_place_type_t<U>, Ts&&... ts);-18- Constraints:
(18.1) — is_same_v<remove_cvref_t<U>, U> is `true`,
(18.2) — derived_from<U, T> is `true`,(18.3) — is_constructible_v<U, Ts> is `true`, and
(18.4) — is_copy_constructible_v<U> is `true`.
-?- Mandates: derived_from<U, T> is `true`.
-19- Effects: […]template<class U, class I, class... Us> constexpr explicit polymorphic(in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);-20- Constraints:
(20.1) — is_same_v<remove_cvref_t<U>, U> is `true`,
(20.2) — derived_from<U, T> is `true`,(20.3) — is_constructible_v<U, initializer_list<I>&, Us...> is `true`,
(20.4) — is_copy_constructible_v<U> is `true`, and
(20.5) — is_default_constructible_v<Allocator> is `true`.
-?- Mandates: derived_from<U, T> is `true`.
-21- Effects: […]template<class U, class I, class... Us> constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);-22- Constraints:
(22.1) — is_same_v<remove_cvref_t<U>, U> is `true`,
(22.2) — derived_from<U, T> is `true`,(22.3) — is_constructible_v<U, initializer_list<I>&, Us...> is `true`, and
(22.4) — is_copy_constructible_v<U> is `true`.
-?- Mandates: derived_from<U, T> is `true`.
-23- Effects: […]
[ 2025-10-07; Reflector poll ]
Set priority to 2 after reflector poll.
"Do we have a concrete use case of an A-like type? Is making the traits give wrong answers preferable to hard errors? I don't think the `polymorphic` part makes sense. Since the constraints still require `U`/`UU` to be complete, either `T` is a base class and it must be complete, or it is not and it doesn't matter."
"The problematic members are non-template functions, so they are instantiated early and the requires clauses are checked too soon. Think this can be solved without giving up SFINAE-friendliness, by making the affected members themselves templates."
The class templates indirect<T> and polymorphic<T> allow the template argument `T` to be an incomplete type.
Both classes can be instantiated when the type `T` is incomplete: constraints are written so that requirements on incomplete types are not evaluated at class instantiation time. For constructors with additional template parameters, there are currently constraints written on the potentially incomplete type `T` and the additional template parameters. Such constraints will not be evaluated at class instantiation time but could be explicitly evaluated in contexts where support for an incomplete `T` is required.template<typename U> class A { U u; public: A(const SomeType&) requires std::is_constructible_v<U, SomeType> { // […] } };
when `U` is indirect<T> or polymorphic<T> for some type `T`, the existence of the requires clause will require that `T` is a complete type for constraints on indirect or polymorphic to be evaluated.
Constraints on `T` should be converted to Mandates on `T` so that constraint evaluation does not require `T` to be a complete type.History | |||
---|---|---|---|
Date | User | Action | Args |
2025-10-07 15:51:28 | admin | set | messages: + msg15129 |
2025-08-23 13:40:52 | admin | set | messages: + msg14950 |
2025-08-20 00:00:00 | admin | create |