|
Boost : |
Subject: Re: [boost] [system] Would it be possible to trial a breaking change to Boost.System and see what happens?
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2018-01-12 19:29:26
On 01/12/18 22:03, Peter Dimov via Boost wrote:
> Andrey Semashev wrote:
>> Â Â void foo(error_code& err)
>> Â Â {
>> Â Â Â Â // Do stuff...
>> Â Â Â Â err = make_error_code(success); // error_code(0, my_category)
>> Â Â }
> ...
>> I suppose, you could argue that I could avoid `err` initialization in
>> `foo`, but that is a matter of taste and whether you want to rely on
>> the initial state of `err` on entry into `foo`.
>
> No, I'm not going to argue that; it's idiomatic to clear `err` on entry:
>
> void foo( error_code& err )
> {
> Â Â err.clear();
> Â Â // do stuff
> }
>
> with the alternative
>
> Â Â err.assign( 0, err.category() );
>
> being used nowadays to avoid the overhead in .clear caused by the "magic
> static" Niall talks about.
>
> This latter "idiom" is obviously broken after NIall's suggested change
> though.
I don't think this matches my intent. The `foo` function belongs to the
domain that defines error codes described by the `my_errors` enum and it
is supposed to return one of those codes. Preserving whatever error
category was set in `err` on entry does not achieve that. What I want is
that `err` has `my_category` unconditionally on return from `foo`.
>> I'm also not happy to have to convert that initialization to
>>
>> Â Â Â Â err = error_code();
>>
>> because it loses information about the error category, which may be
>> useful if I want to print `err` to log even if it is a success.
>
> Interesting. You rely on there being different success error_codes?
Yes, mostly for diagnostic purposes. Although it may also be a useful
feature to check the domain when comparing two error codes.
> How would you suggest we solve the problem of zero being an error in
> some contexts?
Besides moving the check for the error code into the category? I
suppose, `make_error_code` could perform some kind of mapping onto
another enum that has success value of 0. It can be as simple as this:
enum foreign_errors
{
error = 0,
success = 1
};
enum class internal_errors
{
error = -1,
success = 0
};
error_code make_error_code(foreign_errors ec)
{
return error_code(ec - 1, my_category);
}
error_code make_error_code(internal_errors ec)
{
return error_code(ec, my_category);
}
Another solution would be to make error category have a public member,
which is cheap to access, that would return the "success" value.
// std::error_category
class error_category
{
int success_value;
public:
explicit error_category(int sv = 0) : success_value(sv) {}
int get_success_value() const noexcept { return success_value; }
};
class my_category final :
public error_category
{
public:
my_category() : error_category(1) {}
};
bool error_code::operator bool() const
{
return value() != category().get_success_value();
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk