我对于应该如何std::optional
实现副本复制构造器以满足存在的要求感到非常困惑constexpr
。
请注意,在Stackoverflow上还有许多其他问题,类似的问题,例如:
std :: Optional实现为union vs char [] / aligned_storage
但是,这些问题实际上都不是关于COPY CONSTRUCTOR的。我专门询问具有功能签名(从https://en.cppreference.com/w/cpp/utility/optional/optional)的副本构造函数,如下所示:
constexpr optional( const optional& other );
现在,我已经阅读了足够std::optional
的知识,以了解基础知识。实现者通常犯的一个错误是尝试使用来实现它std::aligned_storage
。由于new放置不能在中使用constexpr
(至少在C ++ 17中),因此将不起作用。相反,需要使用联合类型,以便可以直接构造它。就像是:
struct dummy_type {};
union optional_impl
{
dummy_type m_dummy;
T m_value;
};
好的,但是仍然...我仍然看不到应该如何满足将副本构造函数实现为的要求constexpr
。问题是在复制构造函数中,我们需要检查是否other.has_value()
为真。如果是,我们要直接复制*other
,否则我们只想初始化m_dummy
。但是,我们如何在constexpr
复制构造函数中表达此条件决定呢?
constexpr optional( const optional& other ) : m_dummy{}
{
if (other.has_value()) new (&m_value) T(*other); // Wrong! Can't use placement new
}
我看到此工作的唯一方法是使用新的展示位置。
所以我检查了一些实际的实现,例如这里的gcc实现:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/optional#L248
确实……他们只是使用新的展示位置。实际上,复制构造函数不是事件constexpr
(我认为这是一个缺陷)。
这是另一个实现:
https://github.com/akrzemi1/Optional/blob/master/optional.hpp#L416
同样,他们只是使用新的展示位置。
那么如何optional(const optional&)
实现为constexpr
?这是标准中的缺陷吗?
对于C ++ 17,请参见[optional.ctor] / 6:
...如果
is_trivially_copy_constructible_v<T>
为true
,则此构造函数应为constexpr
构造函数。
在这种情况下,联合也将是可复制的,因此没有问题。
在所有其他情况下,constexpr
即使不能在常量表达式中使用构造函数,该构造函数仍将携带说明符。没关系:constexpr
只要函数模板(或类模板的成员函数)具有至少一个可能在常量表达式中使用的实例化,就可以对其进行声明。([dcl.constexpr] / 6)
在C ++ 20中,由于P0602R4,措辞已更改。但是,我认为这并没有改变constexpr
要求。如果T
可以普通复制,则构造函数是普通的,这意味着它也是constexpr
。如果T
不是普通可复制的,那么标准不会说构造函数必须在常量表达式中可用,因此没有这样的要求。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句