C++ constexpr std::可选的可能实现
我正在尝试使用C++ constexpr std::可选的可能实现,c++,c++11,c++14,c++17,C++,C++11,C++14,C++17,我正在尝试使用constepr支持来实现std::optional。用法如下所示: constexpr optional<int> x(123); int arr[*x]; 我还能如何实现这一点呢?您可以使用一个联合体 看看Andrzej是如何做到这一点的: 模板 联合存储 { 无符号字符; T值; constexpr存储_t(平凡_init_t)noexcept:dummy_(){}; 模板 constexpr存储(Args&…Args):值(constexpr_forward
constepr
支持来实现std::optional
。用法如下所示:
constexpr optional<int> x(123);
int arr[*x];
我还能如何实现这一点呢?您可以使用一个联合体
看看Andrzej是如何做到这一点的:
模板
联合存储
{
无符号字符;
T值;
constexpr存储_t(平凡_init_t)noexcept:dummy_(){};
模板
constexpr存储(Args&…Args):值(constexpr_forward(Args)…{}
~storage_t()=默认值;
};
模板
结构可选_基
{
布尔初始值;
储存(t)储存(t);;
constexpr optional_base()noexcept:init_(false),storage_(triple_init){};
显式constexpr可选_基(const T&v):init_u(true),storage_v(v){}
显式constexpr可选_基(T&&v):init_(true),存储_(constexpr_move(v)){
模板显式可选\u基(在位\u t,参数&&…参数)
:init_u(true),存储_u(constepr_uforward(args)…{}
模板
显式可选的\u基(in_place\t,std::initializer\u list il,Args&…Args)
:init_(true),storage_(il,std::forward(args)…{}
~optional_base(){if(init_uu)storage_u.value_uu.T::~T();}
};
注:
如果您想要得到一个既支持在constexpr
函数中的局部变量中使用,又支持在运行时与非平凡可破坏的值一起使用的答案,那么这个解决方案就有一定的复杂性。(可能,您确实希望支持此功能,您不希望您的constexpr optional
泄漏,或者它不是常规可选的替代品。)
这是因为constexpr
析构函数必须根据语言规则设置为默认值,但在某些情况下,这必须与调用泛型参数的析构函数的需要相协调
在Andrzej的例子中,通过使用SFINAE并打开
std::is_minality_destructible
切换到optional_base
类的两个不同实现,一个带有默认析构函数,另一个没有。我在上面的列表中忽略了这一点。如果你想要所有的血淋淋的细节,我建议你读塔尔科夫斯基的代码。< /P>哇,这是我所期望的代码。杰姆斯:欢迎,在C++中实现一个接近语言的特性。你不需要析构函数是constexpr
,这个DIY选项才能在constexpr上下文中使用吗?@emile:@ChrisBeck因此我的评论。我检查了Andrzej的可选实现,现在我看到他有条件地继承了一个constepr_optional_base
,如果T是可微破坏的,则没有析构函数。恐怕您的代码片段只展示了如何为运行时案例实现可选存储。
constexpr optional(const T& value)
noexcept(std::is_nothrow_copy_constructible<T>::value)
: ...
{
new (ptr_to_storage) T(value); // this breaks `constexpr`
}
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() = default;
};
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(); }
};