system_category()
and error_code::error_code()
should be constexpr
Section: 19.5.3.5 [syserr.errcat.objects], 19.5.4.2 [syserr.errcode.constructors] Status: NAD Submitter: Peter Dimov Opened: 2017-06-27 Last modified: 2017-07-12
Priority: Not Prioritized
View all other issues in [syserr.errcat.objects].
View all issues with NAD status.
Discussion:
The default constructor of error_code
should be constexpr
to enable constant initialization;
as a practical matter, there are reports that it regularly shows up in profiles because clearing error codes
is so frequent.
add constexpr
to the declaration of system_category()
in [syserr.errcat.overview]
and [syserr.errcat.objects];
optionally, add constexpr
to the declaration of generic_category()
in the same two sections;
add constexpr
to the default constructor of error_code
in [syserr.errcode.overview] and [syserr.errcode.constructors];
optionally, add constexpr
to the error_code(int val, const error_category& cat)
constructor in the same two sections;
optionally, add constexpr
to error_code::assign
;
optionally, add constexpr
to error_code::clear
;
optionally, add constexpr
to error_code::value
;
optionally, add constexpr
to error_code::category
.
There was an objection that system_category()
can't be made constexpr
because it needs to
"immortalize" the object so that it's not destroyed at process shutdown or module unload, in order for
the error_code
facility to remain usable. However, the following
proof of concept shows how to achieve this and still make the function constexpr
:
#include <new> template<class _Ty> union _Immortalizer { // constructs _Ty, never destroys constexpr _Immortalizer(): __ty() { } ~_Immortalizer() noexcept {} _Immortalizer(const _Immortalizer&) = delete; _Immortalizer& operator=(const _Immortalizer&) = delete; _Ty __ty; }; struct error_category { virtual ~error_category() = default; }; struct system_category_impl : public error_category { }; [[clang::require_constant_initialization]] static const _Immortalizer<system_category_impl> _System_category; constexpr error_category const& system_category() noexcept { return _System_category.__ty; } struct error_code { int val_; const error_category* cat_; constexpr error_code() noexcept : val_(0), cat_(&system_category()) {} constexpr int value() const noexcept { return val_; } constexpr error_category const& category() const noexcept { return *cat_; } }; constexpr error_code s_code; static_assert(s_code.value() == 0); static_assert(&s_code.category() == &system_category());
[2017-07 Toronto Tuesday PM issue prioritization]
NAD; This is a feature request; needs a paper.
Proposed resolution:
This wording is relative to N4659.
Edit 19.5.3.1 [syserr.errcat.overview], class error_category
synopsis, as indicated:
class error_category { public: constexpr error_category() noexcept; virtual ~error_category(); error_category(const error_category&) = delete; error_category& operator=(const error_category&) = delete; virtual const char* name() const noexcept = 0; virtual error_condition default_error_condition(int ev) const noexcept; virtual bool equivalent(int code, const error_condition& condition) const noexcept; virtual bool equivalent(const error_code& code, int condition) const noexcept; virtual string message(int ev) const = 0; bool operator==(const error_category& rhs) const noexcept; bool operator!=(const error_category& rhs) const noexcept; bool operator<(const error_category& rhs) const noexcept; }; constexpr const error_category& generic_category() noexcept; constexpr const error_category& system_category() noexcept;
Edit 19.5.3.5 [syserr.errcat.objects] as indicated:
constexpr const error_category& generic_category() noexcept;[…]
constexpr const error_category& system_category() noexcept;[…]
Edit 19.5.4.1 [syserr.errcode.overview], class error_code
synopsis, as indicated:
class error_code { public: // 19.5.4.2 [syserr.errcode.constructors], constructors constexpr error_code() noexcept; constexpr error_code(int val, const error_category& cat) noexcept; template <class ErrorCodeEnum> error_code(ErrorCodeEnum e) noexcept; // 19.5.4.3 [syserr.errcode.modifiers], modifiers constexpr void assign(int val, const error_category& cat) noexcept; template <class ErrorCodeEnum> error_code& operator=(ErrorCodeEnum e) noexcept; constexpr void clear() noexcept; // 19.5.4.4 [syserr.errcode.observers], observers constexpr int value() const noexcept; constexpr const error_category& category() const noexcept; error_condition default_error_condition() const noexcept; string message() const; explicit operator bool() const noexcept; private: int val_; // exposition only const error_category* cat_; // exposition only };
Edit 19.5.4.2 [syserr.errcode.constructors] as indicated:
constexpr error_code() noexcept;[…]
constexpr error_code(int val, const error_category& cat) noexcept;[…]
Edit 19.5.4.3 [syserr.errcode.modifiers] as indicated:
constexpr void assign(int val, const error_category& cat) noexcept;[…]
constexpr void clear() noexcept;[…]
Edit 19.5.4.4 [syserr.errcode.observers] as indicated:
constexpr int value() const noexcept;[…]
constexpr const error_category& category() const noexcept;[…]