追加到联合向量

Appending to vector of union

我有一个联合,定义如下:

union CellType {
    std::string str;
    int i;
    double d;
    Money<2> m;  // Custom class for fixed-decimal math.
};

然后,我有一个这样的联合向量。

std::vector<CellType> csvLine;

我的问题是,如何将一个值附加到向量的末尾?我通常将 push_back 用于 vector 的字符串、整数等,但是当向量元素是并集时,我无法完全弄清楚语法。任何帮助将不胜感激。

(是的,这个 class 一次读取一行 CSV 文件,如果这有什么不同的话。)

这是失败的 MRE

#include <vector>
#include <iostream>


union CellType {
    std::string str;
    int i;
    double d;
//    Money<2> m;  // Custom class for fixed-decimal math.
};
int main() {
    std::vector<CellType> csvLine;
    CellType c;
    c.str = "foo";
    csvLine.push_back(c);
}

Money 被注释掉了,因为与 MRE 无关

错误

Severity Code Description Project File Line Suppression State Error C2280 'CellType::CellType(void)': attempting to reference a deleted function ConsoleApplication1 C:\work\ConsoleApplication1\ConsoleApplication1.cpp 22

如果您使用的是 C++11 之前的编译器,那么:

Unions cannot contain a non-static data member with a non-trivial special member function (copy constructor, copy-assignment operator, or destructor).

和std::string具有non-trivial以上所有功能。

如果您使用的是支持 C++11 的编译器:

If a union contains a non-static data member with a non-trivial special member function (copy/move constructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer.

If a union contains a non-static data member with a non-trivial default constructor, the default constructor of the union is deleted by default unless a variant member of the union has a default member initializer.

这基本上意味着您没有任何联合构造函数,您需要自己定义复制或移动构造函数才能使以下行起作用:

csvLine.push_back(c);

as push_back 方法将对象复制或移动到其目标位置。

顺便说一句,据我所知,大多数(如果不是全部)标准容器要求它们包含的对象是 copy-constructible 或 move-constructible。您的工会,如此处问题中所述,不是。

引用来源:Union declaration

没有干净的方法来做到这一点,原因很简单,给定这个 union 的任意实例,没有通用的权威方法,template-based function/method,比如std::vector::push_back 知道联合体的哪个成员是活跃的,以便执行 member-specific copy/move 操作,当联合体中至少有一个成员不是 POD 时。声明“此特定联合包含 std::string 因此要 copy/move 您将使用 std::string 的适当 copy/move 运算符”的联合的任何特定实例都没有固有的内容。 C++ 根本无法以这种方式工作,这是 C++ 的基础。没有解决方法,也没有语法。

一般来说,由于 C++ 在 type-safety 中的基础,当与 non-POD 成员如 std::string 一起使用时,固有的 type-unsafe union 会产生功能非常有限的最终结果。

对您来说最不痛苦的是用 C++17 的 std::variant 替换 union,一个 type-safe 联合。 push_back然后变成大胖子nothing-burger。