Я наткнулся на реализацию Optional<T>
который основан на LLVM Optional.h класс и не мог понять, почему он реализован таким, какой он есть.
Короче говоря, я лишь вставляю части, которые не понимаю:
template <typename T>
class Optional
{
private:
inline void* getstg() const { return const_cast<void*>(reinterpret_cast<const void*>(&_stg)); }
typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type storage_type;
storage_type _stg;
bool _hasValue;
public:
Optional(const T &y) : _hasValue(true)
{
new (getstg()) T(y);
}
T* Get() { return reinterpret_cast<T*>(getstg()); }
}
И самая наивная реализация, о которой я мог подумать:
template <typename T>
class NaiveOptional
{
private:
T* _value;
bool _hasValue;
public:
NaiveOptional(const T &y) : _hasValue(true), _value(new T(y))
{
}
T* Get() { return _value; }
}
Вопросы:
storage_type
? каково было намерение автора?new (getstg()) T(y);
? Optional<T>
класс есть над NaiveOptional<T>
)Краткий ответ — «производительность».
Более длинный ответ:
storage_type
обеспечивает область в памяти, которая (а) достаточно большая, чтобы соответствовать типу T, и (b) выровнена должным образом для типа T. Нераспределенный доступ к памяти медленнее. Смотрите также доктор. new (getstg()) T(y)
это размещение нового. Он не выделяет память, а вместо этого создает объект в области памяти, переданной ему. доктор (на всех формах new
— поиск по «размещению новых»).Optional<T>
Реализация не использует динамическое выделение памяти (см. пункт выше).Предполагается, что Std :: option возвращается из функций. Это означает, что вам придется где-то хранить содержимое, на которое ссылается указатель. Это побеждает цель этого класса
Кроме того, вы не можете просто использовать обычный T, потому что в противном случае вам придется каким-то образом его построить. Необязательный параметр позволяет инициализировать содержимое, некоторые типы не могут быть созданы по умолчанию.
Чтобы сделать класс более гибким с точки зрения поддерживаемых типов, используется подходящее и правильно выровненное хранилище. И только если опция active активна, на ней будет создан истинный тип
То, что вы имели в виду, это, вероятно, что-то вроде std::