Je suis tombé sur une implémentation de Optional<T>
qui est basée sur la classe Optional.h de LLVM et n'arrivait pas à comprendre pourquoi elle est implémentée comme elle est.Pourquoi l'option <T> de LLVM est-elle implémentée de cette façon?
Pour être bref, je ne coller les pièces que je ne comprends pas:
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()); }
}
Et la mise en œuvre la plus naïve que je pouvais penser:
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; }
}
Questions:
- Comment interpréter le
storage_type
? quelle était l'intention de l'auteur? - Quelle est la sémantique de cette ligne:
new (getstg()) T(y);
? - Pourquoi l'implémentation naïve ne fonctionne-t-elle pas (ou, quels sont les avantages de la classe
Optional<T>
surNaiveOptional<T>
)?
1) pour le placement mémoire alignée T (voir [doc] (http://en.cppreference.com/w/cpp/types/aligned_storage)), 2) neuf, 3) pros de plus en option naïve: vous enregistrez une allocation dynamique. – Borgleader
Aussi loin que le # 2 va: il s'appelle * placement new * et il dit fondamentalement 'new' pour construire l'objet à un endroit spécifique que vous avez déjà alloué. –
P.S: Dans votre implémentation naïve, le booléen est redondant, vous pouvez simplement comparer à nullptr pour savoir si vous avez une valeur ou non. – Borgleader