Section: 21.3.3 [meta.type.synop] Status: Open Submitter: Daniel Krügler Opened: 2017-03-02 Last modified: 2024-08-21
Priority: 2
View other active issues in [meta.type.synop].
View all other issues in [meta.type.synop].
View all issues with Open status.
Discussion:
LWG 2797 (RU 2) suggests that certain type-traits should be required to
diagnose violations of their pre-conditions. The basic idea is founded and I see no problems for
requiring this for the mentioned traits alignment_of
or is_base_of
,
for example. But if we want to require this diagnostics for some other traits, such as is_convertible
,
is_constructible
(and friends), or is_callable
(and possibly some others), we really should
be sure that our current requirements are OK.
X
:
struct X; // Never defined static_assert(std::is_convertible_v<X, const X&>);
Unfortunately we cannot always allow incomplete types, because most type constructions or conversions indeed require a complete type, so generally relaxing the current restrictions is also not an option.
The core language has a solution for this "small" gap of situations, where the response of the compiler might depend on type completeness: Undefined behaviour. So, I believe we need a somewhat more detailled form to express the intend here. Informally, I would suggest that the program should only be ill-formed in the situation described by LWG 2797, if there exists the possibility that the compiler would require complete types for the considered operation. The example shown above,std::is_convertible_v<X, const X&>
, would never
require the need to complete X
, so here no violation should exist.
The presented example might seem a tiny one, but the Standard Library type traits are extreme fundamental tools and we should
try to not give the impression that an approximate rule of the current type constraints breaks reasonable code.
It is correct, that above example has currently undefined behaviour due to the breakage of pre-conditions, therefore
this issue suggests to fix the current situation before enforcing a diagnostic for such valid situations.
[2017-03-04, Kona]
Set priority to 2. Is related to 2797, but really needs an audit of the type traits.
[2018-08 Batavia Monday issue discussion]
Issues 2797, 2939, 3022, and 3099 are all closely related. Walter to write a paper resolving them.
[2020-02 Prague Thursday issue discussion]
Two of the issues (2797 and 3022) had been resolved by the acceptance of P1285R0.
[2024-05-09; Jonathan provides wording]
We could also relax the type completeness requirements for
reference_converts_from_temporary
and reference_constructs_from_temporary
,
as the result is always false if the first type is a non-reference,
so we don't need complete types in that case.
This doesn't seem important to support, but if we wanted to then we could say:
EitherT
is not a reference type, orT
andU
shall be a complete typecomplete types, cvvoid
, or an arrayarraysof unknown bound.
Previous resolution [SUPERSEDED]:
This wording is relative to N4981.
- In 21.3.5.4 [meta.unary.prop] Table 51, change the Preconditions text for
is_constructible
,is_trivially_constructible
,is_nothrow_constructible
,is_convertible
, andis_nothrow_convertible
, as indicated.
Template Condition Preconditions … … … template<class T, class... Args> struct is_constructible;
For a function type T
or for a cvvoid
typeT
,is_constructible_v<T, Args...>
isfalse
, otherwise see below .Either T
is a reference type andArgs
contains a single type that is similar (7.3.6 [conv.qual]) toremove_reference_t<T>
, orT
and all types in the template parameter packArgs
shall be complete types, cvvoid
, or arrays of unknown bound.… … … template<class T, class... Args> struct is_trivially_constructible;
is_constructible_v<T, Args...>
istrue
and the variable definition foris_constructible
, as defined below, is known to call no operation that is not trivial (6.8.1 [basic.types.general], 11.4.4 [special]).Either T
is a reference type andArgs
contains a single type that is similar (7.3.6 [conv.qual]) toremove_reference_t<T>
, orT
and all types in the template parameter packArgs
shall be complete types, cvvoid
, or arrays of unknown bound.… … … template<class T, class... Args> struct is_nothrow_constructible;
is_constructible_v<T, Args...>
istrue
and the variable definition foris_constructible
, as defined below, is known not to throw any exceptions (7.6.2.7 [expr.unary.noexcept]).Either T
is a reference type andArgs
contains a single type that is similar (7.3.6 [conv.qual]) toremove_reference_t<T>
, orT
and all types in the template parameter packArgs
shall be complete types, cvvoid
, or arrays of unknown bound.… … … - In 21.3.7 [meta.rel] Table 53, change the Comments text for
is_convertible
andis_nothrow_convertible
as indicated.
Template Condition Comments … … … template<class From, class To> struct is_convertible;
see below Either To
is a reference type andFrom
is similar (7.3.6 [conv.qual]) toremove_reference_t<To>
, orFrom
andTo
shall be complete types, cvvoid
, or arrays of unknown bound.template<class From, class To> struct is_nothrow_convertible;
is_convertible_v<From, To>
istrue
and the conversion, as defined byis_convertible
, is known not to throw any exceptions (7.6.2.7 [expr.unary.noexcept]).Either To
is a reference type andFrom
is similar (7.3.6 [conv.qual]) toremove_reference_t<To>
, orFrom
andTo
shall be complete types, cvvoid
, or arrays of unknown bound.
[2024-08-21; Jonathan provides improved wording]
Following on LWG telecon review, change "Args contains a single type that is similar" to "Args contains a single type and that type is similar".
Proposed resolution:
This wording is relative to N4988.
- In 21.3.5.4 [meta.unary.prop] Table 51, change the Preconditions text for
is_constructible
,is_trivially_constructible
,is_nothrow_constructible
,is_convertible
, andis_nothrow_convertible
, as indicated.
Template Condition Preconditions … … … template<class T, class... Args> struct is_constructible;
For a function type T
or for a cvvoid
typeT
,is_constructible_v<T, Args...>
isfalse
, otherwise see below .Either T
is a reference type andArgs
contains a single type and that type is similar (7.3.6 [conv.qual]) toremove_reference_t<T>
, orT
and all types in the template parameter packArgs
shall be complete types, cvvoid
, or arrays of unknown bound.… … … template<class T, class... Args> struct is_trivially_constructible;
is_constructible_v<T, Args...>
istrue
and the variable definition foris_constructible
, as defined below, is known to call no operation that is not trivial (6.8.1 [basic.types.general], 11.4.4 [special]).Either T
is a reference type andArgs
contains a single type and that type is similar (7.3.6 [conv.qual]) toremove_reference_t<T>
, orT
and all types in the template parameter packArgs
shall be complete types, cvvoid
, or arrays of unknown bound.… … … template<class T, class... Args> struct is_nothrow_constructible;
is_constructible_v<T, Args...>
istrue
and the variable definition foris_constructible
, as defined below, is known not to throw any exceptions (7.6.2.7 [expr.unary.noexcept]).Either T
is a reference type andArgs
contains a single type and that type is similar (7.3.6 [conv.qual]) toremove_reference_t<T>
, orT
and all types in the template parameter packArgs
shall be complete types, cvvoid
, or arrays of unknown bound.… … … - In 21.3.7 [meta.rel] Table 53, change the Comments text for
is_convertible
andis_nothrow_convertible
as indicated.
Template Condition Comments … … … template<class From, class To> struct is_convertible;
see below Either To
is a reference type andFrom
is similar (7.3.6 [conv.qual]) toremove_reference_t<To>
, orFrom
andTo
shall be complete types, cvvoid
, or arrays of unknown bound.template<class From, class To> struct is_nothrow_convertible;
is_convertible_v<From, To>
istrue
and the conversion, as defined byis_convertible
, is known not to throw any exceptions (7.6.2.7 [expr.unary.noexcept]).Either To
is a reference type andFrom
is similar (7.3.6 [conv.qual]) toremove_reference_t<To>
, orFrom
andTo
shall be complete types, cvvoid
, or arrays of unknown bound.