是否可以让“命名构造函数”返回私有构造的、不可移动、不可复制的 std::Optional

2023-12-07

我主要从事不允许抛出异常的系统级 C++ 项目,但(理所应当)强烈鼓励使用 RAII。现在,我们使用许多 C++ 程序员熟悉的臭名昭著的技巧来处理构造函数失败的问题,例如:

  1. 简单的构造函数,然后调用bool init(Args...)做困难的事情
  2. 真正的构造函数,然后进行检查bool is_valid() const
  3. 堆分配static unique_ptr<MyType> create(Args...)

当然,这些都有缺点(堆分配、无效和“移动”状态等)。

我的公司终于更新编译器并将允许glorious使用C++17。自 C++17 以来的特性std::optional<T>而且,最重要的是,强制复制省略,我希望我可以大大简化我们所有的类,使其看起来像这样:

class MyType {
 public:
  static std::optional<MyType> create() {
    // If any of the hard stuff fails, return std::nullopt
    return std::optional<MyType>(std::in_place, 5, 'c');
  }
  ~MyType() {
    // Cleanup mArg0 and mArg1, which are always valid if the object exists
  }

  // ... class functionality ...

  // Disable default constructor, move, and copy.
  // None of these are needed because mandatory copy elision
  // allows the static function above to return rvalue without
  // copy or move operations
  MyType() = delete;

  MyType(const MyType&) = delete;
  MyType(MyType&&) = delete;

  MyType& operator=(const MyType&) = delete;
  MyType& operator=(MyType&&) = delete;

private:
  MyType(ArgT0 arg0, ArgT1 arg1) : mArg0(arg0), mArg1(arg1) {}
  ArgT0 mArg0;
  ArgT1 mArg1;
};

请注意这有多好:静态函数确保在创建对象之前完成所有困难的工作,缺乏默认的 ctor/move 意味着对象永远不会以无效或移动状态存在,私有构造函数确保用户不会意外地跳过命名的演员。

不幸的是,由于演员是私人的,std::is_constructable_t<MyType>检查失败,因此in_place的构造函数optionalSFINAE 出局了。

如果我做了两件事之一,但我不想做这两件事,则此代码有效:

  1. 将 ctor 设为公开(但现在该类的用户可能会意外地绕过指定的 ctor)
  2. 允许移动操作(但现在我必须处理无效的对象)

我也尝试过这个,但它不起作用,因为std::optional需要一个移动运算符才能使其工作:

static std::optional<MyType> create() {
  // If any of the hard stuff fails, return std::nullopt
  return std::optional<MyType>(MyType(5, 'c'));
}

我是否可能缺少一些技巧或咒语才能使其正常工作,或者我是否达到了 C++17 允许的限制?

Thanks!


如果你想让任何间接对象构造工作(emplace以各种形式,in_place的构造函数optional, make_shared等),相关构造函数必须是公共的。您可以使用称为私钥的东西将构造函数公开,而不允许所有公开使用。

基本上,您创建一个类型(称之为Key) 其默认构造函数是私有的。该类没有成员,也不执行任何操作。它声明MyType是...的朋友Key;这意味着只有成员MyType可以构建一个。

现在,让所有MyType的构造函数public,但他们都采取Key const&作为第一个参数。这意味着理论上anyone可以打电话给他们,但实际上只有拥有Key实例实际上可以调用它们。的成员MyType可以创建这样的实例,并且可以将这些实例传递给optional's in_place构造函数或任何其他间接机制。这有效地为间接构造机制提供了对构造函数的私有访问权限。

这是处理转发类型私有访问的标准习惯用法。事实上,假设我们可以写一个通用的key<T>像这样输入:

template<typename T>
class key
{
private:
  key() = default;
  key(int) {} //Not an aggregate

  friend T;
};

一张小纸条。由于 C++11 pre-C++20 的一个烦恼,除了默认/删除的复制/移动/默认构造函数之外,任何没有成员和构造函数的类型都被视为聚合。这是真实的even if你明确地= default它的默认构造函数。因此,该类型可以进行聚合初始化,没有公共/私有区别。也就是说,任何人都可以通过这样做来调用您的私钥构造函数:MyType({}, <params>);.

为了避免这种情况,您需要给出Key额外的(私有)构造函数或以其他方式阻止它成为聚合。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以让“命名构造函数”返回私有构造的、不可移动、不可复制的 std::Optional ? 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 按成员序列化

    我已经实现了template
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • InvokeDynamic 参数的动态类型

    为了支持动态类型和方法分派 我的编程语言引入了一种称为dynamic 当调用类型为的被调用者的方法时dynamic 编译器首先将被调用者和所有参数压入堆栈 然后生成一个invokedynamic指令而不是正常的invoke 操作说明 该指令
  • Chrome 扩展程序:sendMessage 不起作用

    我已经读过几次 Google 关于 消息传递 的文档 并且可能查看了 10 多个具有相同问题的其他问题 并且已经尝试了他们的大多数 解决方案 和我下面的内容的一些变体 这就是黑魔法吧 不管怎样 就这样吧 清单文件 manifest vers
  • 未使用 MSBuild、Teamcity 复制 Bin 文件夹

    我有一个非常奇怪的问题 我创建了一个自定义 MSBuild 任务 它将 MVC 项目所需的所有文件移动到特定位置 以便我们可以发布它 当我在我的计算机上本地触发脚本时 这工作正常 但一旦我检查此更改并且 Teamcity 运行脚本 它就会复
  • MySQL 从表 WHERE 条件多行中选择一个字段

    试图找到答案 但还是找不到 表格如下 id keyword value 1 display 15 6 1 harddrive 320 1 ram 3 所以我需要的是这样的 从这个表中选择一个 id keyword display and v
  • C# 对象数组,非常大,寻找更好的方法

    好的 所以在我的一个项目中 我试图重新设计它存储某些变量的方式 我有一个简单的对象数组 这些对象引用的类是 class Blocks public byte type Block Empty byte lastblock Block Zer
  • Wix:通过在立即操作中设置属性来访问延迟操作中的属性:字典中不存在给定的键

    我正在关注几个来源 SO 帖子 甚至是 Wix 安装程序书 这就是我目前在立即自定义操作中设置两个属性 然后尝试在延迟操作中读取它的方式 但是 它不起作用 失败并回滚 并且我不断收到System Collections Generic Ke
  • 在 Mac OS X 上以编程方式为 Matplotlib 选择正确的后端

    我有一个程序集成了 tkinter GUI 和 matplotlib 图 使用 pyplot 为了让这个程序在各种 Mac 平台上正常工作 我遇到了无尽的麻烦 主要问题似乎是后端的适当选择 在某些情况下 程序运行良好没有问题 在其他情况下
  • 为低于 31 的 API 创建 LocationRequest

    我有compileSdkVersion 32 现在我可以创建LocationRequest仅使用LocationRequest Builder LocationRequest create 目前不可用 这意味着我什至无法调用这个已弃用的静态
  • 将指数分布叠加到直方图上

    如何在时间间隔直方图上叠加指数分布 直方图看起来像指数分布 当我尝试以与叠加法线曲线类似的方式创建直方图时 我得到以下结果 Error in xy coords x y x and y lengths differ 我可以自己创建直方图 它
  • 用于 Caffe 的 Python 还是 Matlab?

    我将致力于在 Caffe 中实现 DQN 和 Google DeepMind 的最新扩展 为此 我将编写一个模拟器 代替 Atari 模拟器 来为代理创建培训体验 我的问题是 Matlab 或 Python 的 Caffe 接口中哪一个最成
  • 有没有办法通过sql获取Windows任务管理器详细信息?

    我无法访问客户端的 Windows 远程计算机 我仅通过 tsql 连接他们的数据库服务器 我需要检查哪些进程占用了更多内存并通知他们 有没有tsql查询来获取windows进程 对的 这是可能的 您可以致电TASKLIST命令通过xp c
  • 错误:未定义对“cv::imread(std::string const&, int)”的引用

    我是 Qt 新手 我有一个需要在 Qt 中配置 OpenCV 的项目 我尝试在 Qt 中运行一个简单的代码 但出现此错误 未定义的引用 cv imread std string const int 这是我的代码 include opencv
  • 当键为数字时,如何从多维数组中回显单个值?

    以此数组为例 Array events gt Array 0 gt Array event gt Array category gt seminars sales status gt Live 如何检索类别的值 我尝试过各种组合 例如 ec
  • PHP 将重复行插入数据库

    我使用以下代码将用户插入到名为 accounts 的表中 session start include include connect php Posted information from the form put into variabl
  • jQuery 事件:检测 div 的 html/文本的更改

    我有一个 div 它的内容一直在变化 是吗 ajax requests jquery functions blur等等等等 有没有办法可以随时检测到 div 上的任何变化 我不想使用任何间隔或检查的默认值 像这样的事情会做 mydiv co
  • 如何测试 dockerignore 文件?

    读完后 dockerignore文档 我想知道有没有办法测试一下 Examples node modules 如何检查我的 dockerfile 忽略正确的文件和目录 扩展至VonC的建议 这是一个示例构建命令 您可以使用它来使用当前文件夹
  • Spring Data Rest @EmbeddedId 无法从 Post Request 构造

    我有一个 JPA 实体Person和一个实体Team 两者都由一个实体连接人与团队 该连接实体与以下对象保持多对一关系Person和一到Team 它有一个由 id 组成的多列键Person和Team 由 EmbeddedId 表示 为了将嵌
  • Endpoint 与 Windows 沉浸式项目版本 1 不兼容

    由于某种原因 我使用 添加服务引用 向导为 wcf 服务生成代码时出错 Custom tool warning No endpoints compatible with version 1 of windows immersive proj
  • 如何在复选框单击时选择 jqGrid 行?

    下面是我的 jqGrid 代码 我想选择行或突出显示当前行 当我checkjqgrid 行内的特定复选框 现在onSelectRow我正在检查复选框 var xmlDoc parseXML xml configDiv empty div w
  • 是否可以让“命名构造函数”返回私有构造的、不可移动、不可复制的 std::Optional

    我主要从事不允许抛出异常的系统级 C 项目 但 理所应当 强烈鼓励使用 RAII 现在 我们使用许多 C 程序员熟悉的臭名昭著的技巧来处理构造函数失败的问题 例如 简单的构造函数 然后调用bool init Args 做困难的事情 真正的构