kamek
kamek

Reputation: 2440

How do I properly use boost::optional with types with public member variables?

Here is a motivating example demonstrating what my problem is:

struct Foo
{
  int x;
  int y;
};

boost::optional<Foo> opt_foo;

opt_foo->x = 1; // legal
opt_foo->y = 2; // legal

auto foo = opt_foo.get(); // legal (returns valid instance of Foo with x = 1 and y = 2)

if (opt_foo) // false
{
  ...
}

I understand that in order for the optional object to be initialized, I would have to use boost::optional<Foo> opt_foo = Foo();. However, I was surprised to see that if it is forgotten, I can still do all the things I marked as legal (especially get()). Was this intended behavior? Is there any way I can make opt_foo consider itself initialized without boost::optional<Foo> opt_foo = Foo();?

Upvotes: 0

Views: 908

Answers (1)

Jack
Jack

Reputation: 133567

Under the hood, boost::optional is implemented as a simple

struct {
  bool _present;
  T _t;
}

So whether you explicitly initialize or not the optional with a value, the storage for this value already exists, and in C++ we don't usually like to pay for what we don't need (eg. checking if an optional is present on each call of operator->).

It is duty of the developer to only try to access the optional value if it is present, as explained in the documentation:

An attempt to extract the contained value of an uninitialized optional object is an undefined behaviour (UB). This implementation guards the call with BOOST_ASSERT. Therefore you should be sure that the contained value is there before extracting.

Actually your code should SIGABRT on the assertion, are you running it in debug mode?

You can use value() if you want to avoid any risk of UB (but you need to place that in a try block).

Upvotes: 1

Related Questions