This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.

### 1237. Constrained `error_code`/`error_condition members`

Section: 19.5 [syserr] Status: C++11 Submitter: Daniel Krügler Opened: 2009-10-14 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [syserr].

View all issues with C++11 status.

Discussion:

I'm just reflecting on the now SFINAE-constrained constructors and assignment operators of `error_code` and `error_condition`:

These are the only library components that are pro-actively announcing that they are using `std::enable_if` as constraining tool, which has IMO several disadvantages:

1. With the availability of template default arguments and decltype, using `enable_if` in the C++0x standard library, seems unnecessary restricting implementation freedom. E.g. there should be no need for a useless specification of a dummy default function argument, which only confuses the reader. A more reasonable implementation could e.g. be

   >     template <class ErrorCodeEnum
   >      class = typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type>
   >     error_code(ErrorCodeEnum e);

   As currently specified, the function signatures are so unreadable, that errors quite easily happen, see e.g. 1229.

2. We have a lot of constrained functions in other places, that now have a standard phrase that is easily understandable:

   > Remarks: This constructor/function shall participate in overload resolution if and only if X.

   where X describes the condition. Why should these components deviate?

3. If `enable_if` would not be explicitly specified, the standard library is much better prepared for the future. It would also be possible, that libraries with partial support for not-yet-standard-concepts could provide a much better diagnostic as is possible with `enable_if`. This again would allow for experimental concept implementations in the wild, which as a result would make concept standardization a much more natural thing, similar to the way as templates were standardized in C++.

   In summary: I consider it as a library defect that `error_code` and `error_condition` explicitly require a dependency to `enable_if` and do limit implementation freedom and I volunteer to prepare a corresponding resolution.

[ 2009-10-18 Beman adds: ]

> I support this proposed resolution, and thank Daniel for writing it up.

[ 2009-10 Santa Cruz: ]

> Moved to Ready.

Proposed resolution:

[ Should this resolution be accepted, I recommend to resolve 1229 as NAD ]

1. In 19.5.4.1 [syserr.errcode.overview]/1, class `error_code`, change as indicated:

   >     // 19.5.2.2 constructors:
   >     error_code();
   >     error_code(int val, const error_category& cat);
   >     template <class ErrorCodeEnum>
   >       error_code(ErrorCodeEnum e,
   >         typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type * = 0);

   >     // 19.5.2.3 modifiers:
   >     void assign(int val, const error_category& cat);
   >     template <class ErrorCodeEnum>
   >       typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::typeerror_code&
   >         operator=(ErrorCodeEnum e);
   >     void clear();

2. Change 19.5.4.2 [syserr.errcode.constructors] around the prototype before p. 7:

   >     template <class ErrorCodeEnum>
   >     error_code(ErrorCodeEnum e,
   >       typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type * = 0);

   > > Remarks: This constructor shall not participate in overload resolution, unless `is_error_code_enum<ErrorCodeEnum>::value == true`.

3. Change 19.5.4.3 [syserr.errcode.modifiers] around the prototype before p. 3:

   >     template <class ErrorCodeEnum>
   >       typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::typeerror_code&
   >         operator=(ErrorCodeEnum e);

   > > Remarks: This operator shall not participate in overload resolution, unless `is_error_code_enum<ErrorCodeEnum>::value == true`.

4. In 19.5.5.1 [syserr.errcondition.overview]/1, class `error_condition`, change as indicated:

   >     // 19.5.3.2 constructors:
   >     error_condition();
   >     error_condition(int val, const error_category& cat);
   >     template <class ErrorConditionEnum>
   >       error_condition(ErrorConditionEnum e,
   >         typename enable_if<is_error_condition_enum<ErrorConditionEnum>::type* = 0);

   >     // 19.5.3.3 modifiers:
   >     void assign(int val, const error_category& cat);
   >     template<typenameclass ErrorConditionEnum>
   >       typename enable_if<is_error_condition_enum<ErrorConditionEnum>, error_code>::typeerror_condition &
   >         operator=( ErrorConditionEnum e );
   >     void clear();

5. Change 19.5.5.2 [syserr.errcondition.constructors] around the prototype before p. 7:

   >     template <class ErrorConditionEnum>
   >       error_condition(ErrorConditionEnum e,
   >         typename enable_if<is_error_condition_enum<ErrorConditionEnum>::value>::type* = 0);

   > > Remarks: This constructor shall not participate in overload resolution, unless `is_error_condition_enum<ErrorConditionEnum>::value == true`.

6. Change 19.5.5.3 [syserr.errcondition.modifiers] around the prototype before p. 3:

   >     template <class ErrorConditionEnum>
   >       typename enable_if<is_error_condition_enum<ErrorConditionEnum>::value>::typeerror_condition&
   >         operator=(ErrorConditionEnum e);

   > > Remarks: This operator shall not participate in overload resolution, unless `is_error_condition_enum<ErrorConditionEnum>::value == true`.

   > > Postcondition: `*this == make_error_condition(e)`.

   > > Returns: `*this`