Почему LLVM является опциональным & lt; T & gt; реализован таким образом?

Я наткнулся на реализацию 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; }
}

Вопросы:

  1. Как я могу интерпретировать storage_type? каково было намерение автора?
  2. Какова семантика этой строки: new (getstg()) T(y); ?
  3. Почему не работает наивная реализация (или, какие плюсы Optional<T> класс есть над NaiveOptional<T>)

3

Решение

Краткий ответ — «производительность».

Более длинный ответ:

  1. storage_type обеспечивает область в памяти, которая (а) достаточно большая, чтобы соответствовать типу T, и (b) выровнена должным образом для типа T. Нераспределенный доступ к памяти медленнее. Смотрите также доктор.
  2. new (getstg()) T(y) это размещение нового. Он не выделяет память, а вместо этого создает объект в области памяти, переданной ему. доктор (на всех формах new — поиск по «размещению новых»).
  3. Наивная реализация работает, но имеет худшую производительность. Он использует динамическое распределение памяти, что часто может быть узким местом. Optional<T> Реализация не использует динамическое выделение памяти (см. пункт выше).
6

Другие решения

Предполагается, что Std :: option возвращается из функций. Это означает, что вам придется где-то хранить содержимое, на которое ссылается указатель. Это побеждает цель этого класса

Кроме того, вы не можете просто использовать обычный T, потому что в противном случае вам придется каким-то образом его построить. Необязательный параметр позволяет инициализировать содержимое, некоторые типы не могут быть созданы по умолчанию.

Чтобы сделать класс более гибким с точки зрения поддерживаемых типов, используется подходящее и правильно выровненное хранилище. И только если опция active активна, на ней будет создан истинный тип

То, что вы имели в виду, это, вероятно, что-то вроде std::

-1

По вопросам рекламы [email protected]