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.

### 2992. `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.

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.

1. 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;

2. Edit 19.5.3.5 [syserr.errcat.objects] as indicated:

   >     constexpr const error_category& generic_category() noexcept;

   > > […]

   >     constexpr const error_category& system_category() noexcept;

   > > […]

3. 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
   >     };

4. Edit 19.5.4.2 [syserr.errcode.constructors] as indicated:

   >     constexpr error_code() noexcept;

   > > […]

   >     constexpr error_code(int val, const error_category& cat) noexcept;

   > > […]

5. Edit 19.5.4.3 [syserr.errcode.modifiers] as indicated:

   >     constexpr void assign(int val, const error_category& cat) noexcept;

   > > […]

   >     constexpr void clear() noexcept;

   > > […]

6. Edit 19.5.4.4 [syserr.errcode.observers] as indicated:

   >     constexpr int value() const noexcept;

   > > […]

   >     constexpr const error_category& category() const noexcept;

   > > […]