On 01/16/18 20:09, Peter Dimov via Boost wrote:
Andrey Semashev wrote:
Calling (virtual) `error_category::failure` early is a waste if the user doesn't want to call that function himself. For instance, he may want to test specific error codes instead.
It can still be worth it because it's more likely to occur in a context where the compiler can see what category is being used. When you have
error_code ec( r, system_category() );
and system_category() is constexpr, the compiler knows with certainty what the call category().failed( r ) will do, so it will replace it with r != 0.
This will only be possible if the implementation of the category is visible at the point of `error_code` construction. I'm assuming that typically it is not. If the category is supposed to be visible then there is no reason to make that method virtual. Make it a regular function and change the constructor like this: template< typename Category, enable_if_t< is_base_of_t< error_category, Category > >
constexpr error_code(int v, const Category &cat) : _value(v), _is_failure(cat.is_failure(v)), _category(&cat) {} Although, honestly, I don't see much point in having that function in the category at this point. The code should be more clean if it tested the code against the enum values instead of `int`. So instead of this: bool my_category::is_failure(int err) { return static_cast< my_error >(err) < my_error::min_success || static_cast< my_error >(err) > my_error::max_success; } I would prefer this: error_code make_error_code(my_error err) { return error_code(static_cast< int >(err), err < my_error::min_success || err > my_error::max_success, my_category); } Note that this approach allows to generate `error_code` objects with the same category from multiple different enums. I think, someone mentioned a use case for this earlier in the discussion - when multiple enums basically map onto the common error domain, which has a single error category.