Danqi Wang
Danqi Wang

Reputation: 1637

Conditionally construct a `boost::optional` member variable on class constructor member initializer list

Suppose I have a non-copyable and non-moveable class Person:

struct Person
{
  int m_icNum;

  explicit Person(int icNum) : m_icNum(icNum) {}
  Person (const Person & other) = delete;
  Person (Person && other) = delete;
};

And another class PersonContainer:

struct PersonContainer
{
  boost::optional<Person> m_person;

  explicit PersonContainer(int icNum)
  : m_person( icNum >= 0 ? Person(icNum) : boost::none) // this does not compile because the two operands of ternary operator ? must have the same type
  {}
};

Apparently I cannot construct m_person using ternary expression in the initializer list. An alternative is to construct it in the ctor body using boost::in_pace, but I wonder if there is a nice way to construct it in the initializer list.

Upvotes: 3

Views: 325

Answers (2)

Danqi Wang
Danqi Wang

Reputation: 1637

Inspired by @kabanus' comment, this can be achieved using boost::in_place_init_if:

struct PersonContainer
{
  boost::optional<Person> m_person;

  explicit PersonContainer(int icNum)
  : m_person(boost::in_place_init_if, icNum >= 0, icNum)
  {}
};

Upvotes: 3

Kaldrr
Kaldrr

Reputation: 2850

You can explicitly specify the ternary operator return type to be boost::optional<Person>.

explicit PersonContainer(int icNum)
  : m_person( icNum >= 0 ? boost::optional<Person>{Person(icNum)} : 
                           boost::optional<Person>{boost::none}) 
  {}

Upvotes: 1

Related Questions