Boost logo

Boost :

Subject: Re: [boost] [outcome] Possible extensions/changes to std::experimental::expected
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2017-05-29 22:59:43


On 30/05/2017 03:07, Niall Douglas wrote:
>> Sorry, I probably should have said "since *I assume* outcome<error_code>
>> is legal".
>>
>> I can imagine some scenarios where that might be useful (perhaps as part
>> of some error translation code which wants to return a modified value
>> but can also fail) but I suppose that would complicate the constructors
>> a bit so I can understand why it'd be disallowed, and it should be rare
>> enough not to really bite anyone.
>>
>> (Although tagged constructors to resolve that ambiguity wouldn't be an
>> issue if you could only create an errored outcome with a helper like
>> make_unexpected...)
>
> It's disallowed purely to avoid SFINAE on constructors and thus improve
> compile times.

That's why I mentioned tagged constructors. No SFINAE needed.
Something like:

template<typename T>
class result
{
public:
     struct error_tag {};

     outcome(const T& val) { set_value(val); }
     outcome(error_code err, error_tag) { set_error(err); }
     //...
};

template<typename T>
result<T> make_error(error_code err)
{
     return result<T>(err, result<T>::error_tag());
}

You could even make the error_tag constructor private and make_error a
friend to ensure that make_error is the only possible way to produce an
errored result. (Or keep the constructor public but make error_tag
private; same effect.)

With this setup, there is no ambiguity when T is error_code -- user code
with "return err" will return the error code as the value, and with
"return make_error(err)" will return it as an error.

I'm not sure I would actually *recommend* this design, I'm just pointing
out that it's possible and removes the ambiguity without any SFINAE.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk