2016-06-18 10 views
2

Ich versuche std::optional mit constexpr Unterstützung als eine Praxis zu implementieren. Die Nutzung wird so etwas wie:consExpr Std :: optional mögliche Implementierung

constexpr optional<int> x(123); 
int arr[*x]; 

Beim Versuch, das ich dieses Problem hätte zu implementieren, die ich nicht in der Lage zu lösen: Innerhalb eines optional<T> Objekts, verwende ich ein std::aligned_storage_t<sizeof (T), alignof (T)> Objekt den Wert zu speichern und Verwenden Sie die neue Platzierung in optional<T> 's Konstruktor, um Wert in den Speicher zu erstellen. Aber Platzierung neu kann nicht in einem constexpr Konstruktor verwendet werden:

constexpr optional(const T& value) 
    noexcept(std::is_nothrow_copy_constructible<T>::value) 
    : ... 
{ 
    new (ptr_to_storage) T(value); // this breaks `constexpr` 
} 

Wie sonst kann ich das umsetzen?

Antwort

1

Sie könnten eine Union verwenden.

Check out, wie Andrzej tut es:

https://github.com/akrzemi1/Optional/blob/master/optional.hpp#L282

template <class T> 
union storage_t 
{ 
    unsigned char dummy_; 
    T value_; 

    constexpr storage_t(trivial_init_t) noexcept : dummy_() {}; 

    template <class... Args> 
    constexpr storage_t(Args&&... args) : value_(constexpr_forward<Args>(args)...) {} 

    ~storage_t() {} 
}; 


template <class T> 
struct optional_base 
{ 
    bool init_; 
    storage_t<T> storage_; 

    constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; 

    explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} 

    explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} 

    template <class... Args> explicit optional_base(in_place_t, Args&&... args) 
     : init_(true), storage_(constexpr_forward<Args>(args)...) {} 

    template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)> 
    explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args) 
     : init_(true), storage_(il, std::forward<Args>(args)...) {} 

    ~optional_base() { if (init_) storage_.value_.T::~T(); } 
}; 
+0

Wow, das ist wirklich viel mehr Code, den ich jemals erwartet. –

+6

@ZizhengTai Willkommen in C++ – James

+3

@James gut, willkommen zu implementieren eine nahe Sprache-Level-Funktion in C++. ;) – Yakk

Verwandte Themen