Boost logo

Boost :

Subject: [boost] [optional] get() misses optional r-value overload in contrast to operator* and value()
From: Viktor Sehr (viktor.sehr_at_[hidden])
Date: 2018-03-23 15:32:41


Hi Andrzej, thanks for your response.

I do not get the same result as you using latest visual studio (as for
today 15.6.4 with std=latest), I'm not sure on what would be the correct
behavior but to me it seems erroneous that the unique_ptr has lost it's
value. Note that using std::optional yields the same result as below.

auto func0() {
  return boost::make_optional(std::make_unique<int>(42));
}
const auto& x = func0().value();
assert(x); // true
assert(*x = 42); // true

I agree that declaring x as a reference rather than a value is sketchy,
this is just how I happened to find the bug, I suppose there are other
cases which might be errorous.
While on the subject I think that boost::optional should add the member
function has_value() in addition to is_initialized() to make it
syntactically compatible with std::optional.

best regards/Viktor

On Fri, Mar 23, 2018 at 3:36 AM Andrzej Krzemienski <akrzemi1_at_[hidden]>
wrote:

> Hi Viktor,
> Thank you for reporting this. This is an omission (a bug) that I will need
> to fix. I have created an issue in GitHub to track it:
> https://github.com/boostorg/optional/issues/51.
>
> On the other hand, I do not think that the bug is causing an UB any more
> than function `value()` in your example. Unless something has changed in
> the way temporaries' life is prolonged in C++17. I tested it for `int`s and
> all tests work fine. I tested it on `unique_ptr<int>`:
>
> ```
> #include <memory>
> #include <iostream>
> #include <boost/optional.hpp>
>
> using boost::optional;
>
> optional<std::unique_ptr<int>> func() {
> return boost::make_optional(std::unique_ptr<int>(new int{3}));
> }
>
> int main()
> {
> auto const& p = func().value();
> std::cout << (bool)p << std::endl; // outputs: 0
> }
> ```
>
> And even when I use `value()` I do not get the intuitive result. I would
> recommend catching the result by value rather than by reference, and all
> surprises will be gone, including the one from your example.
>
> Regards,
> &rzej;
>
> 2018-03-23 2:04 GMT+01:00 Viktor Sehr via Boost <boost_at_[hidden]>:
>
>> Both *value()* and *operator** has an overload to handle if the
>> *optional<T>* object is an r-value. However *get()* does not have the
>> r-value overload.
>>
>> This leads to undefined behavior using *get()*, but not with *operator**
>> and *value()*, in the following example:
>
>
>>
>> auto func0() {
>> return optional<int>{3};
>> }
>> auto func1() {
>> const auto& x = func0().get(); // Undefined behavior
>> const auto& y = func0().value(); // Correct
>> const auto& z = *func0(); // Correct
>> }
>>
>> Is this intended, I can't see any reason why the r-value overload of
>> .get()
>> would be missing?
>> Otherwise, the following overload of .get() should be added:
>>
>> reference_type_of_temporary_wrapper get() && {
>> BOOST_ASSERT(this->is_initialized());
>> return boost::move(this->get_impl());
>> }
>>
>>
>> /Viktor Sehr, Software Developer at Toppluva
>>
>> _______________________________________________
>> Unsubscribe & other changes:
>> http://lists.boost.org/mailman/listinfo.cgi/boost
>>
>
>


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