为什么std :: variant在union可以不能保存数组对象类型?

时间:2018-03-15 05:08:29

标签: c++ visual-c++ c++17 variant c++20

这是一个简单的例子, 我们可以像这样定义一个低级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)编译器发出了编译错误:

  

错误C2338变体要求所有Ts都是非数组   对象类型([variant.variant] / 2)。

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

1 个答案:

答案 0 :(得分:17)

P0510R0之后national body comment US116删除了对数组的支持,我在下面重现:

  

支持    数组替代方案似乎不起作用   正如所料。     例如,如果有任何替代方案   是一个数组,当前规范无法满足   所有6个关系运算符都需要子句,并且   输了(不应参与超载解决)   复制构造函数,移动构造函数,复制赋值   运算符,移动赋值运算符(尽管如此)   交换功能将正常工作)。     这很难   激活数组替代    - 尽我所能   理解,它必须安置没有   参数,以便对数组进行值初始化,以及   那么每个元素的值可以被指定为   需要。     如果这些问题中的许多问题都将得到解决   通过存储a来实现数组替代   std :: array代替,然后将仅显示的数组成员(std :: array)暴露给get   功能,但这似乎是一个实验性的变化   应该调查下一个标准。对于   C ++ 17,我们应该放弃对数组的支持(但不是   std :: array)作为替代方案,以便在下一个标准中自由地支持它们。

似乎很可能在std::variant提案的初始修订期间,对数组类型的可能性没有太多考虑,尽管有些人认为给出了参考和void类型(在P0510R0中也删除了对这些类型的支持),并且一些修订通过强加Destructible要求(最终标准文本中不存在)隐式禁止数组。一旦将标准草案发送给国家成员机构,就会有人注意到阵列会造成困难,因为它们无法以预期的方式进行复制,移动或比较。所有这些问题也许可以通过规范和实现中的特殊套管阵列(成员比较等)来解决,但这项工作留待将来修订标准。