2016-06-18 60 views
2

我试图实现std::optionalconstexpr支持作为一种做法。用法将是这样的:constexpr std ::可选的可能实现

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

当试图实现这个我有这个问题,我一直没能解决:内部的optional<T>对象,我用一个std::aligned_storage_t<sizeof (T), alignof (T)>对象存储的值,在optional<T>的构造函数中使用放置新元素来构建存储中的值。

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

我还能如何实现这一点:但是放置新不能在constexpr构造函数中使用吗?

回答

1

你可以使用联合。

退房安杰是如何做的:

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

哇,这是我有生以来预期真的太多的代码。 –

+6

@ZizhengTai欢迎来到C++ – James

+3

@james,欢迎在C++中实现近乎语言级的功能。 ;) – Yakk