为什么std::variant不能持有数组对象类型,而联合可以?

14

这里是一个简单的例子, 我们可以像这样定义一个低级别的union

static union
{
    uint64_t a;
    uint8_t b[8];
};

但是我们不能像这样声明std::variant(请不要在意语法,如果我有错请指出,只需抓住思想)

std::variant<uint64_t, uint8_t[8]> v

cppReference明确表示:

模板参数

类型 - 可存储在此变体中的类型。所有类型必须是(可能带有cv修饰符的)非数组对象类型。

此外,MSVC-v141(C++17)编译器给出了一个编译错误:

Error C2338 所有的Ts必须是非数组对象类型([variant.variant]/2)。


std::variant主要是一个类模板,因此,问题在于它无法推断数组类型的存储方式,因为它只需要数据布局/表示?


2
这可能对你有所帮助-https://www.ojdip.net/2013/10/implementing-a-variant-type-in-cpp/ - user3839622
4
我猜这与数组除了数据成员之外无法复制,以及具有指针的隐式转换有关。通过不支持原始数组,所有这些复杂性都可以避免。您总是可以使用std::array - Cheers and hth. - Alf
@Cheersandhth.-Alf 你是指这样写吗 -> std::variant<uint64_t, std::array<uint8_t>[8]> v 类似这样? - Buddhika Chaturanga
是的 - Cheers and hth. - Alf
4
std::array<uint8_t, 8> - llllllllll
谢谢大家... - Buddhika Chaturanga
1个回答

21
P0510R0美国国家机构评论US116之后,取消了对数组的支持。以下是评论的复制:
“数组替代品的支持似乎不能按预期工作。例如,如果任何一个替代品是一个数组,则当前规范未能满足所有6个关系运算符的要求子句,并且失去(不参与重载分辨率)复制构造函数、移动构造函数、复制赋值运算符、移动赋值运算符(尽管交换函数将正确工作)。激活数组替代品很困难-据我所知,必须使用无参数放置以对数组进行值初始化,然后可以根据需要分配每个元素的值。如果通过存储std::array实现数组替代品,则许多这些问题将得到解决,然后将公开仅用于阐述的std::array成员(of the std::array)给get函数,但这似乎是一个试验性的变化,应该在下一个标准中进行调查。对于C++17,我们应该放弃对数组(但不是std::array)的支持作为替代品,以便在下一个标准中自由地支持它们。”
std::variant提案的初期修订中,似乎没有考虑到数组类型的可能性,虽然一些考虑已经给予了引用和void类型的情况(对这些的支持也在P0510R0中被删除),而且一些修订通过施加Destructible要求(该要求不在最终标准文本中),隐含地禁止了数组。一旦草案标准被发送给国家成员机构,有人注意到数组会带来困难,因为它们不能按预期方式进行复制、移动或比较。所有这些问题都可以通过在规范和实现中特殊处理数组(逐成员比较等)来解决,但这项工作留待标准的未来修订。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接