- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试实现一个自定义变体类型,它使用 union 来存储各种不同类型的数据。在字段type_id
中我打算存储union中存储的数据是哪种类型。 union 包含非平凡的成员。这是我当前的实现:
struct MyVariant {
enum { t_invalid, t_string, t_int, t_double, t_ptr, t_dictionary } type_id;
union {
int as_int;
double as_double;
std::string as_string;
std::unique_ptr<int> as_ptr;
std::map<int, double> as_dictionary;
};
};
我尝试创建一个 MyVariant
的实例,如下所示:
MyVariant v;
我收到错误消息:调用 MyVariant 的隐式删除默认构造函数。因此,我尝试手动实现构造函数,如下所示:
MyVariant() : type_id{t_int}, as_int{0} {}
这给了我类似的错误消息:尝试使用已删除的函数。接下来,我尝试实现以下构造函数:
MyVariant(int value) : type_id{t_int}, as_int{value} {}
并按如下方式构建我的实例:
MyVariant v{123};
=> 相同的错误消息:尝试使用已删除的函数。
我也开始实现一个复制构造函数,它看起来像下面这样。但是,这当然对编译器错误没有帮助。
MyVariant::MyVariant(const MyVariant& other)
{
type_id = other.type_id;
switch (type_id) {
case t_invalid:
break;
case t_string:
new (&as_string) std::string();
as_string = other.as_string;
break;
case t_int:
as_int = other.as_int;
break;
case t_double:
as_double = other.as_double;
break;
case t_ptr:
new (&as_ptr) std::unique_ptr<int>(nullptr);
as_ptr = std::make_unique<int>(*other.as_ptr);
break;
case t_dictionary:
new (&as_dictionary) std::map<int, double>();
// TODO: copy values from other
break;
}
}
我使用 Xcode 和 Apple LLVM 6.1 作为编译器。
主要问题是:为什么我会收到编译器错误以及我必须如何修改我的代码才能使其编译?
另一个问题是:我对构造函数和复制构造函数的实现是否正确?
最佳答案
你的 union 有string
、unique_ptr
和map
类型的数据成员,所有这些都有重要的默认/复制/移动构造函数、复制/移动赋值运算符和析构函数。因此,对于您的 union ,所有这些都被隐式删除。
§9.5/2 [class.union]
... [ Note: If any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union. —end note ]
所以你必须为你的 union 手动实现这些。至少,为了能够创建 MyVariant
的实例,该类需要是可构造和可破坏的。所以你需要
MyVariant() : type_id{t_int}, as_int{0} {}
~MyVariant()
{
switch(type_id)
{
case t_int:
case t_double:
// trivially destructible, no need to do anything
break;
case t_string:
as_string.~basic_string();
break;
case t_ptr:
as_ptr.~unique_ptr();
break;
case t_dictionary:
as_dictionary.~map();
break;
case t_invalid:
// do nothing
break;
default:
throw std::runtime_error("unknown type");
}
}
您的复制构造函数实现看起来有效,但我要做的不同之处在于,不是首先默认构造成员,然后从源对象复制,而是在放置新调用本身中复制构造。
MyVariant(const MyVariant& other)
{
type_id = other.type_id;
switch (type_id) {
case t_invalid:
break;
case t_string:
new (&as_string) auto(other.as_string);
break;
case t_int:
as_int = other.as_int;
break;
case t_double:
as_double = other.as_double;
break;
case t_ptr:
new (&as_ptr) auto(std::make_unique<int>(*other.as_ptr));
break;
case t_dictionary:
new (&as_dictionary) auto(other.as_dictionary);
break;
}
请注意,如果 unique_ptr
成员处于事件状态,并且正在通过基类指针存储指向某个派生类实例的指针,那么您的复制构造函数实现将仅复制基类部分。
最后,除非您将此作为学习练习,否则我强烈建议您使用 Boost.Variant而不是自己滚动。
关于c++ - 包含非平凡成员 union 的类的构造函数和复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30492927/
test = (function(){var key = 200; return {getKey : function(){return key} }; })(); test.
如果这个问题可能一直被问到,我很抱歉,但我进行了搜索,但找不到足够的答案。 如果公共(public)成员/方法正在访问私有(private)成员/字段,如何禁用它们的继承? 所以考虑一下: publi
重要的澄清:一些评论者似乎认为我是从 union 复制的。仔细查看 memcpy,它从一个普通的旧 uint32_t 地址复制而来,该地址不包含在 union 中。另外,我正在(通过 memcpy)复
spinner 通常只显示一个字符串,在我想分配 IDpersonne 和 Name 的情况下,旋转器必须告诉我名字。当我得到选定的项目时,我必须得到 ID。我该怎么做? 最佳答案 我假设您已将项目排
A 类的实例是 B 类的公共(public)成员。B 类的实例也是 A 的公共(public)成员。在什么情况下可能需要这种实现?我的意思是是否有一个或多个标准场景需要这种实现方式?更具体的细节:我有
我如何设置我的 web.config 以使用表单例份验证,将成员身份提供程序设置为 ActiveDirectoryMembershipProvider 并使用内置登录控件。这样我就可以使用有效的事件目
这个问题已经有答案了: Should methods in a Java interface be declared with or without a public access modifier?
因此根据定义,类中的私有(private)数字在序列化时以类名作为前缀。这对我来说是一个问题,我希望能够序列化/保存/反序列化一个确切的对象,但是 php 所做的是给我另一个 classname+va
我实现了一个成员? clojure 中的函数如下: (defn member? [item seq] (cond (empty? seq) false (= item (first
我在这里的问题似乎总是与使用函数有关。它仍然让我困惑!在本教科书练习中,我被要求按值传递结构,然后调整它并按引用传递。最初我设计的代码是在 main 中完成所有工作。现在我正在传递值。所以我添加了新函
所以我有这些变量 List files, images = new List(); string rootStr; 还有这个线程函数 private static int[] thread_searc
我对 C++ 模板和尝试弄清楚部分模板特化还比较陌生。我正在使用模板实现几个相关的数据结构:用于概率存在/不存在查询的布隆过滤器(基于位数组),以及用于丰度查询的计数布隆过滤器(带有整数数组)。我从以
例如在 java 中,我在外部类和内部类中声明并初始化了一个 JButton,我决定在某些情况下将其隐藏,这是一种安全的编程实践吗? 最佳答案 内部类的全部目的是它们可以访问到环绕内部类的外部类。 所
我有一个使用库进行通信的类: class Topic { Topic( Type T, String name ); }; class Reader { Reader (Topic, Stri
我在两个单独的文件中有以下代码。 package animal; public class Frog { protected void ribbit() { Syste
我有一个分数列表。使用这些,我需要从 redis 排序集中提取值。 我知道我可以使用 zrangebyscore - 但如果我提供的列表中的分数不连续怎么办?在这种情况下,我不能依赖 zrangeby
过去几年我一直被 C# 编码宠坏了,现在我又回到了 C++ 并发现我在处理本应很简单的东西时遇到了麻烦。我正在为 gamedev 使用名为 DarkGDK 的第三方库(任何以 db 为前缀的命令),但
我正在关注 Brian Harvey 从 2011 年开始在 UC Berkeley site 上的 SICP 讲座。 .他正在使用 STk interpreter教这门课,我正在使用带有 DrRac
在这段代码中,为什么在运算符重载中无法访问我的类的私有(private)字段? (请注意,这只是一个 MRE,不是完整代码) template class Frac template Frac o
在命名命名空间类中,我将一个类(位于全局命名空间中)声明为友元。 但是,后一个类不能访问前一个类的私有(private)成员。为什么是这样?有什么办法可以解决吗? Bob.h namespace AB
我是一名优秀的程序员,十分优秀!