Boost logo

Boost :

Subject: Re: [boost] [optional] Safe optional
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2014-11-18 01:22:33


Le 17/11/14 10:24, Andrzej Krzemienski a écrit :
> 2014-11-17 9:40 GMT+01:00 Matt Calabrese <rivorus_at_[hidden]>:
>
>> On Sun, Nov 16, 2014 at 11:04 PM, Andrzej Krzemienski <akrzemi1_at_[hidden]>
>> wrote:
>>
>>> Hi Everyone,
>>> I would like to run an idea through everyone in this list. There is a
>>> recurring complaint about Boost.Optional that it allows you to do
>> "unsafe"
>>> things:
>>> 1. Inadvertent mixed comparisons between T and optional<T>
>>> 2. Unintended conversion from T to optional<T>
>>> 3. "Unchecked" access to the contained object, which causes an UB when
>>> performed on an uninitialized optional object.
>>>
>>> There are valid reasons why optional is defined the way it is defined.
>> But
>>> at the same time the complaints above are also valid. This makes some
>>> people abandon Boost.Optional and use their own alternative.
>>>
>> I don't immediately see the problem with the mixed comparisons between T
>> and optional T... except maybe confusion regarding optional<bool> or
>> bool-like types. Is this what you're referring to? If so, then I sort of
>> disagree that it's a legitimate problem. If you are not talking about
>> issues relating to bool or have some really compelling optional<bool>
>> cases, can you point me to examples as to why this is suggested to be
>> unsafe. I don't really care that much about the mixed comparisons, but I
>> consider them pretty benign and if people find it useful then I won't
>> remove it unless the current uses are fully considered.
>>
>> As for #2, I think I agree that conversion should probably be more explicit
>> and is potentially a step in a positive direction.
>>
>> As for #3, if you are implying the alternative is to throw an exception,
>> then I'd say that's a flat-out no. That's a logic error and we shouldn't
>> throw an exception. The only thing that comes of that is people using the
>> exception for basic control flow -- if they knew the optional didn't point
>> to anything, then they wouldn't be dereferencing it. If they THOUGHT the
>> optional pointed to something and it didn't, then they have a bug, which
>> means the way to "handle" it is to fix the code. If they don't know at the
>> time of the access whether there was something there or not, then they
>> shouldn't deference it, using an exception for control flow. In that last
>> case, they should either be explicitly branching or they should use some
>> kind of visitation. If you're not talking about exceptions, then what
>> exactly are you proposing?
>>
> No, no exceptions.
> The solution is based on the observation that there is a limited number of
> things you can do with optional<T>
>
> optional<int> oi = ...;
>
> 1:
> if (oi) doSomething(*oi);
> else doSomethingElse(); // or nothing
>
> 2:
> if (oi) doSomething(*oi);
> else doSomething(-1); // use default value
>
> 3:
> if (!oi) oi = (int)getIntByOtherMeans();
> doSomething(*oi); // now it is safe
>
> Now we simply provide a dedicated interface for each of these three usages:
>
> 1:
> oi.use(&doSomething, &doSomethingElse); // or use lambdas
This is the idea of visitation and try-catch behind this function. What
would be the result of this use function? Should both functions return
the same type?

I would suggest to call this accept or match. In addition this could be
a free function

auto x = match(oi,
     [] (int i) {},
     [] () {}
);
The function could take several optional

auto x = match(make_tuple(oi, os),
     [] (int i, string const& s) {},
     [] (...) {}
);

>
> 2:
> doSomething(oi.value_or(-1));
I believed this was already part of the interface.

>
> 3:
> doSomething(oi.value_or_eval(getIntByOtherMeans));
>
>

Why do we need a new safe_optional class to add these features?

Best,
Vicente


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