make_error_code
and make_error_condition
are customization pointsSection: 19.5 [syserr] Status: C++23 Submitter: Jonathan Wakely Opened: 2021-10-31 Last modified: 2023-11-22
Priority: 2
View all other issues in [syserr].
View all issues with C++23 status.
Discussion:
The rule in 16.4.2.2 [contents] means that the calls to
make_error_code
in 19.5.4.2 [syserr.errcode.constructors]
and 19.5.4.3 [syserr.errcode.modifiers] are required to call
std::make_error_code
,
which means program-defined error codes do not work.
The same applies to the make_error_condition
calls in
19.5.5.2 [syserr.errcondition.constructors] and
19.5.5.3 [syserr.errcondition.modifiers].
They need to use ADL. This is what all known implementations (including Boost.System) do.
[2022-01-29; Reflector poll]
Set priority to 2 after reflector poll.
Previous resolution [SUPERSEDED]:
This wording is relative to N4901.
Modify 19.5.2 [system.error.syn] as indicated:
-1- The value of each
enum errc
constant shall be the same as the value of the<cerrno>
macro shown in the above synopsis. Whether or not the<system_error>
implementation exposes the<cerrno>
macros is unspecified.-?- Invocations of
make_error_code
andmake_error_condition
shown in subclause 19.5 [syserr] select a function to call via overload resolution (12.2 [over.match]) on a candidate set that includes the lookup set found by argument dependent lookup (6.5.4 [basic.lookup.argdep]).-2- The
is_error_code_enum
andis_error_condition_enum
templates may be specialized for program-defined types to indicate that such types are eligible forclass error_code
andclass error_condition
implicit conversions, respectively.[Note 1: Conversions from such types are done by program-defined overloads of
make_error_code
andmake_error_condition
, found by ADL. —end note]
[2022-08-25; Jonathan Wakely provides improved wording]
Discussed in LWG telecon and decided on new direction:
make_error_code
and make_error_condition
to 16.4.2.2 [contents] as done for swap
.
Describe form of lookup used for them.error_code
and error_condition
constructors in terms of "Effects: Equivalent to" so that the
requirements on program-defined overloads found by ADL are implied by those
effects.[2022-09-07; Jonathan Wakely revises wording]
Discussed in LWG telecon. Decided to change "established as-if by performing unqualified name lookup and argument-dependent lookup" to simply "established as-if by performing argument-dependent lookup".
This resolves the question of whether std::make_error_code(errc)
,
std::make_error_code(io_errc)
, etc. should be visible to the
unqualified name lookup. This affects whether a program-defined type that
specializes is_error_code_enum
but doesn't provide an overload of
make_error_code
should find the overloads in namespace std
and consider them for overload resolution, via implicit conversion to
std::errc
, std::io_errc
, etc.
[2022-09-23; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
[2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4910.
Modify 16.4.2.2 [contents] as indicated:
-3- Whenever an unqualified name other than
swap
,make_error_code
, ormake_error_condition
is used in the specification of a declarationD
in 17 [support] through 32 [thread] or D [depr], its meaning is established as-if by performing unqualified name lookup (6.5.3 [basic.lookup.unqual]) in the context ofD
.[Note 1: Argument-dependent lookup is not performed. — end note]
Similarly, the meaning of a qualified-id is established as-if by performing qualified name lookup (6.5.5 [basic.lookup.qual]) in the context of
D
.[Example 1: The reference to
is_array_v
in the specification ofstd::to_array
(23.3.3.6 [array.creation]) refers to::std::is_array_v
. — end example][Note 2: Operators in expressions (12.2.2.3 [over.match.oper]) are not so constrained; see 16.4.6.4 [global.functions]. — end note]
The meaning of the unqualified name
swap
is established in an overload resolution context for swappable values (16.4.4.3 [swappable.requirements]). The meanings of the unqualified namesmake_error_code
andmake_error_condition
are established as-if by performing argument-dependent lookup (6.5.4 [basic.lookup.argdep]).
Modify 19.5.4.2 [syserr.errcode.constructors] as indicated:
error_code() noexcept;
-1- Postconditions:val_ == 0
andcat_ == &system_category()
.
-1- Effects: Initializesval_
with0
andcat_
with&system_category()
.error_code(int val, const error_category& cat) noexcept;
-2- Postconditions:val_ == val
andcat_ == &cat
.
-2- Effects: Initializesval_
withval
andcat_
with&cat
.template<class ErrorCodeEnum> error_code(ErrorCodeEnum e) noexcept;-3- Constraints:
is_error_code_enum_v<ErrorCodeEnum>
istrue
.
-4- Postconditions:*this == make_error_code(e)
.
-4- Effects: Equivalent to:error_code ec = make_error_code(e); assign(ec.value(), ec.category());
Modify 19.5.4.3 [syserr.errcode.modifiers] as indicated:
template<class ErrorCodeEnum> error_code& operator=(ErrorCodeEnum e) noexcept;-2- Constraints:
is_error_code_enum_v<ErrorCodeEnum>
istrue
.
-3- Postconditions:*this == make_error_code(e)
.
-3- Effects: Equivalent to:error_code ec = make_error_code(e); assign(ec.value(), ec.category());-4- Returns:
*this
.
Modify 19.5.5.2 [syserr.errcondition.constructors] as indicated:
error_condition() noexcept;
-1- Postconditions:val_ == 0
andcat_ == &generic_category()
.
-1- Effects: Initializesval_
with0
andcat_
with&generic_category()
.error_condition(int val, const error_category& cat) noexcept;
-2- Postconditions:val_ == val
andcat_ == &cat
.
-2- Effects: Initializesval_
withval
andcat_
with&cat
.template<class ErrorConditionEnum> error_condition(ErrorConditionEnum e) noexcept;-3- Constraints:
is_error_condition_enum_v<ErrorConditionEnum>
istrue
.
-4- Postconditions:*this == make_error_condition(e)
.
-4- Effects: Equivalent to:error_condition ec = make_error_condition(e); assign(ec.value(), ec.category());
Modify 19.5.5.3 [syserr.errcondition.modifiers] as indicated:
template<class ErrorConditionEnum> error_condition& operator=(ErrorConditionEnum e) noexcept;-2- Constraints:
is_error_condition_enum_v<ErrorConditionEnum>
istrue
.
-3- Postconditions:*this == make_error_condition(e)
.
-3- Effects: Equivalent to:error_condition ec = make_error_condition(e); assign(ec.value(), ec.category());-4- Returns:
*this
.