
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@gmail.com> 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@lists.boost.org>:
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