Как уже упоминали другие, идеальная вещь, чтобы сделать, это изменить с union
на boost::variant<>
.
Однако, если это невозможно, вы можете реализовать POD-аппроксимацию boost::optional<>
следующим образом:
Осуществление
template <typename T>
class Optional
{
T value;
bool valid;
public:
// for the if(var) test
operator bool() const { return valid; }
// for assigning a value
Optional<T> &operator=(T rhs)
{
value = rhs;
valid = true;
return *this;
}
// for assigning "empty"
Optional<T> &operator=(void *)
{
valid = false;
return *this;
}
// non-const accessors
T &operator*() { return value; }
T *operator->() { return &value; }
// const accessors
const T &operator*() const { return value; }
const T *operator->() const { return &value; }
};
Средства доступа к const необходимы, если вы держите экземпляр const Optional<>
.
Использование
Как и указатель, Optional<T>
не имеет состояния по умолчанию и должен быть инициализирован, прежде чем вы сможете на него положиться (ноль или нет).
В отличие от boost::optional<T>
, Optional<T>
не может быть создан из его типа значения T
, и может быть создан только из другого Optional<T>
.
Если вы действительно хотите его инициализировать или обнулить при создании, вы можете создать вспомогательный класс с operator Optional<T>()
. Я решил не делать этого.
Строительство
Optional<details> additional_info;
Optional<details> more_info(additional_info);
Назначение
// if there's no additional info
additional_info = 0;
// if there is extended info
details x;
// ...populate x...
additional_info = x;
Доступ к данным
if( extended_info )
{
extended_info->member;
// - or -
details &info = *extended_info;
}
Так что - все оказалось не так уж плохо. Это не заставляет меня чувствовать себя довольно тепло и нечетко, но это делает работу.