Created on 2017-06-27.00:00:00 last changed 90 months ago
Proposed resolution:
This wording is relative to N4659.
Edit [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 [syserr.errcat.objects] as indicated:
constexpr const error_category& generic_category() noexcept;[…]
constexpr const error_category& system_category() noexcept;[…]
Edit [syserr.errcode.overview], class error_code synopsis, as indicated:
class error_code { public: // [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; // [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; // [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 [syserr.errcode.constructors] as indicated:
constexpr error_code() noexcept;[…]
constexpr error_code(int val, const error_category& cat) noexcept;[…]
Edit [syserr.errcode.modifiers] as indicated:
constexpr void assign(int val, const error_category& cat) noexcept;[…]
constexpr void clear() noexcept;[…]
Edit [syserr.errcode.observers] as indicated:
constexpr int value() const noexcept;[…]
constexpr const error_category& category() const noexcept;[…]
[ 2017-07 Toronto Tuesday PM issue prioritization ]
NAD; This is a feature request; needs a paper.
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());
History | |||
---|---|---|---|
Date | User | Action | Args |
2017-07-12 01:58:24 | admin | set | messages: + msg9355 |
2017-07-12 01:58:24 | admin | set | status: new -> nad |
2017-06-28 17:06:31 | admin | set | messages: + msg9308 |
2017-06-27 00:00:00 | admin | create |