How to disengage std::experimental::optional?
Asked Answered
C

3

5

With Boost I can create an optional in-place with:

boost::optional<boost::asio::io_service::work> work = boost::in_place(boost::ref(io_service));

And disengage it with:

work = boost::none;

With C++14 / experimental support, I can instead construct an optional in-place with:

std::experimental::optional<boost::asio::io_service::work> work;
work.emplace(boost::asio::io_service::work(io_service));

But I'm at a loss for how to disengage it...

Cleft answered 12/11, 2014 at 21:37 Comment(0)
P
10
work = std::experimental::nullopt;

should disengage work.
The library fundamental TS specifies in [optional.nullopt]:

The struct nullopt_t is an empty structure type used as a unique type to indicate a disengaged state for optional objects.

There is an appropriate assignment operator, [optional.object.assign]:

optional<T>& operator=(nullopt_t) noexcept;

Effects: If *this is engaged calls val->T::~T() to destroy the contained value; otherwise no effect.

To avoid constructing a nullopt_t object every time, a constant of this type is already declared:

struct nullopt_t{see below};
constexpr nullopt_t nullopt(unspecified);

Preventer answered 12/11, 2014 at 21:42 Comment(3)
In any case the only(ish) way you can construct an object of type nullopt_t is by copying nullopt.Peace
@LucDanton ... or copying an object of type nullopt_t that was initialized by copying nullopt.Preventer
And so, ultimately, it all comes down to nullopt.Peace
F
3

This simplest way to disengage an optional is with foo = {};, which is resolved as move assignment from a disengaged prvalue optional. The specification actually goes out of its way to enable this syntax which would otherwise be ambiguous with assignment from the contained type. (See [optional.object.assign] para 18-23 in N4023 for details)

Finespun answered 12/11, 2014 at 22:21 Comment(1)
Hmm, with my example that throws a compiler error: error: use of deleted function 'std::experimental::optional<boost::asio::io_service::work>& std::experimental::optional<boost::asio::io_service::work>::operator=(std::experimental::optional<boost::asio::io_service::work>&&)'Cleft
C
1

Having read through the headers, the correct way to disengage the std::experimental::optional appears to be:

work = std::experimental::nullopt;
Cleft answered 12/11, 2014 at 21:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.