附加到联合向量

发布于 2025-01-14 22:54:19 字数 966 浏览 5 评论 0原文

我有一个并集,定义如下:

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

然后,我有一个此类并集的向量。

std::vector<CellType> csvLine;

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

(是的,这个类一次读取一行 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

错误

无关

严重性代码描述项目文件行抑制状态 错误 C2280 'CellType::CellType(void)':尝试引用已删除的函数 ConsoleApplication1 C:\work\ConsoleApplication1\ConsoleApplication1.cpp 22

I have a union, defined like so:

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

Then, I have a vector of such unions.

std::vector<CellType> csvLine;

My question is, how do I append a value to the end of the vector? I normally use push_back for vectors of strings, ints, etc., but can't quite figure out the syntax when the vector elements are unions. Any help would be appreciated.

(Yes, this class is reading CSV files a line at a time, if that makes any difference.)

here is failing 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 commented out because because irrelevant to the MRE

Error

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感性不性感 2025-01-21 22:54:19

没有干净的方法可以做到这一点,原因很简单,给定此联合的任意实例,对于通用的、基于模板的函数/方法,例如 std:: ,没有权威的方法。 vector::push_back 了解联合体中的哪个成员处于活动状态,以便在联合体中至少有一个成员不是 POD 时执行特定于成员的复制/移动操作。联合体的任何特定实例都没有固有的内容表明“此特定联合体包含 std::string,因此要复制/移动它,您将使用 std::string”适当的复制/移动运算符”。 C++ 根本不以这种方式工作,这是 C++ 的基础。没有解决方法,也没有语法。

一般来说,由于 C++ 的类型安全基础,本质上类型不安全的 union 在与非 POD 成员(例如 std::string)一起使用时,会产生结束结果能力相当有限。

对您来说最简单的方法是将您的 union 替换为 C++17 的 std::variant(类型安全的联合)。 push_back 然后就变成了一个又大又胖、什么都没有的汉堡。

There is no clean way to do this for the simple reason that given an arbitrary instance of this union there is no authoritative way for a generic, template-based function/method, like std::vector::push_back to know which member of the union is active, in order to execute the member-specific copy/move operation, when at least one member of the union is not a POD. There's nothing inherent to any particular instance of a union that states "this specific union contains a std::string so to copy/move it you will use std::string's appropriate copy/move operator". C++ simply does not work this way, this is fundamental to C++. There is no workaround, and no syntax for this.

In general, due to C++'s foundation in type-safety, an inhererently type-unsafe union, when used together with non-POD members like std::string, produces an end result with quite limited capabilities.

The least amount of pain for you would be to replace your union with C++17's std::variant, a type-safe union. push_back then becomes a big, fat, nothing-burger.

溺ぐ爱和你が 2025-01-21 22:54:19

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

联合不能包含具有非平凡的非静态数据成员
特殊成员函数(复制构造函数、复制赋值运算符、
或析构函数)。

std::string 具有上述所有功能。

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

如果联合包含具有非平凡的非静态数据成员
特殊成员函数(复制/移动构造函数、复制/移动赋值、
或析构函数),该函数默认在联合中被删除,并且
需要由程序员明确定义。

如果联合包含具有非平凡的非静态数据成员
默认构造函数,union的默认构造函数被删除
默认情况下,除非联合体的变体成员有默认成员
初始化器。

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

csvLine.push_back(c);

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

顺便说一句,据我记得大多数(如果不是全部)标准容器要求它们包含的对象是可复制构造或可移动构造的。正如问题中所提出的,您的工会不是。

引用来源:联盟声明

If you are using pre C++11 compiler then:

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

and std::string has non-trivial all of the above functions.

If you are using compiler which supports 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.

This basically means that you don't have any of the union constructors and you need to define copy or move constructor yourself for the following line to work:

csvLine.push_back(c);

as push_back method either copies or moves the object to its target location.

BTW, as far as I remember most (if not all) standard containers require that objects they contain are copy-constructible or move-constructible. Your union, as presented here in a question, isn't.

Source of the quotations: Union declaration

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文