This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.
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.
Suggested resolution: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;[…]