C++ 变体访问重载函数

2024-03-17

我想在变体上执行重载函数。以下代码块可以工作并编译,但是visit调用似乎过于复杂。为什么我不能简单地写:

std::visit(&f, something);

工作版本和上下文:

#include <variant>
#include <string>
#include <iostream>
#include <functional>

struct A {
        std::string name = "spencer";
};

struct B {
        std::string type = "person";
};

struct C {
        double age = 5;
};

void f(A a) {
        std::cout << a.name << std::endl;
}

void f(B b) {
        std::cout << b.type << std::endl;
}

void f(C c) {
        std::cout << c.age << std::endl;
}


int main() {
        std::variant<A, B, C> something{B{}};
        std::visit([](auto&& x) {f(x);}, something);
}

有没有更简单的方法?


std::visit(&f, something);

这是无效的,因为f不是一个单一的函数。&f说“给我一个指针f". But f不是一回事;它是三个函数,它们碰巧共享一个名称,并具有三个单独的指针。

std::visit([](auto&& x) {f(x);}, something);

这将创建一个基于模板的闭包,该模​​板生成在编译时进行分派的代码。实际上,它的工作原理就像我们所做的一样

void f(A a) {
  std::cout << a.name << std::endl;
}

void f(B b) {
  std::cout << b.type << std::endl;
}

void f(C c) {
  std::cout << c.age << std::endl;
}

struct F {  
  template<typename T>
  void operator()(T x) {
    f(x);
  }
};

int main() {
  std::variant<A, B, C> something{B{}};
  std::visit(F(), something);
}

这将迫使 C++ 编译器在模板扩展期间生成类似的内容

void f(A a) {
  std::cout << a.name << std::endl;
}

void f(B b) {
  std::cout << b.type << std::endl;
}

void f(C c) {
  std::cout << c.age << std::endl;
}

struct F {
  void operator()(A x) {
    f(x);
  }
  void operator()(B x) {
    f(x);
  }
  void operator()(C x) {
    f(x);
  }
};

int main() {
  std::variant<A, B, C> something{B{}};
  std::visit(F(), something);
}

如果你想消除 lambda 包装器,你需要一个可以作为参数传递的可调用对象,而函数指针是不够的,因为函数指针无法进行重载决策。我们总是可以显式地创建一个函子对象。

struct F {
  void operator()(A a) {
    std::cout << a.name << std::endl;
  }
  void operator()(B b) {
    std::cout << b.type << std::endl;
  }
  void operator()(C c) {
    std::cout << c.age << std::endl;
  }
};

int main() {
  std::variant<A, B, C> something{B{}};
  std::visit(F(), something);
}

您是否认为这种方法比以前的方法更干净取决于您。一方面,它更像是传统的 OOP 访问者模式,因为我们有一个对象进行访问。另一方面,如果我们能够通过name一个函数并且让 C++ 理解我们的意思,但这要么需要特殊的 C++ 语法std::visit或以多方法形式运行时调度。不管怎样,这不太可能很快发生,或者根本不可能发生。

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

C++ 变体访问重载函数 的相关文章

  • 静态只读字符串数组

    我在我的 Web 应用程序中使用静态只读字符串数组 基本上数组有错误代码 我将所有类似的错误代码保存在一个数组中并检查该数组 而不是检查不同常量字符串中的每个错误代码 like public static readonly string m
  • 为什么在连接两个字符串时 Python 比 C 更快?

    目前我想比较 Python 和 C 用来处理字符串的速度 我认为 C 应该比 Python 提供更好的性能 然而 我得到了完全相反的结果 这是 C 程序 include
  • CLR 2.0 与 4.0 性能比较?

    如果在 CLR 4 0 下运行 为 CLR 2 0 编译的 NET 程序会运行得更快吗 应用程序配置
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • 代码 GetAsyncKeyState(VK_SHIFT) & 0x8000 中的这些数字是什么?它们是必不可少的吗?

    我试图在按下按键的简单动作中找到这些数字及其含义的任何逻辑解释 GetAsyncKeyState VK SHIFT 0x8000 可以使用哪些其他值来代替0x8000它们与按键有什么关系 GetAsyncKeyState 根据文档返回 如果
  • ComboBox DataBinding 导致 ArgumentException

    我的几个类对象 class Person public string Name get set public string Sex get set public int Age get set public override string
  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 从同一个类中的另一个构造函数调用构造函数

    我有一个带有两个构造函数的类 C 这是代码片段 public class FooBar public FooBar string s constructor 1 some functionality public FooBar int i
  • 使用可变参数包类型扩展的 C++ 函数调用者包装器

    我绑定了一些 API 并且绑定了一些函数签名 如下所示 static bool WrapperFunction JSContext cx unsigned argc JS Value vp 我尝试将对象和函数包装在 SpiderMonkey
  • 使用valgrind进行GDB远程调试

    如果我使用远程调试gdb我连接到gdbserver using target remote host 2345 如果我使用 valgrind 和 gdb 调试内存错误 以中断无效内存访问 我会使用 target remote vgdb 启动
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • 如何在richtextbox中使用多颜色[重复]

    这个问题在这里已经有答案了 我使用 C windows 窗体 并且有 richtextbox 我想将一些文本设置为红色 一些设置为绿色 一些设置为黑色 怎么办呢 附图片 System Windows Forms RichTextBox有一个
  • 灵气序列解析问题

    我在使用 Spirit Qi 2 4 编写解析器时遇到一些问题 我有一系列键值对以以下格式解析

随机推荐

  • Google Datastore查询NodeJS应用程序如何获取实体的ID

    我有一个使用 Google Datastore 的 NodeJS 应用程序 我设置了一个基本查询 它可以从数据库返回数据 问题 如何检索返回的每个实体的 ID 我需要结果集中的 ID 以便可以在 UI 上向用户显示它 这是到目前为止的 No
  • iOS Appstore应用程序覆盖企业应用程序

    我公司拥有Appstore和企业发行许可证 我们将通过企业许可证使用当前的测试版进行演示 一些用户将下载企业应用程序来测试测试版本 应用商店发布后 我们希望应用商店应用程序覆盖演示期间下载的企业测试版 这样 下载测试版应用程序的人就可以切换
  • Apache Flink 环境中的 AWS SDK 冲突

    我正在尝试将我的作业部署到 Flink 环境 但总是收到错误 java lang NoSuchMethodError com amazonaws AmazonWebServiceRequest putCustomQueryParameter
  • Cocoa Autolayout:内容拥抱与内容压缩阻力优先级

    我在有关 Cocoa Autolayout 的 Apple 文档中找不到有关内容拥抱和压缩阻力之间差异的明确答案 有人可以解释一下它们的用法和区别吗 概念的快速总结 拥抱 gt 内容不想增长 抗压 gt 内容不想收缩 Example 假设你
  • ImportError:没有名为 sklearn.cross_validation 的模块

    我在 Ubuntu 14 04 中使用 python 2 7 我使用以下命令安装了 scikit learn numpy 和 matplotlib sudo apt get install build essential python de
  • 如何使用 FormData 将文件发送到 Nodejs 并让 Node 发回确认消息?

    您好 我正在处理这个简单的表单 尝试使用以下命令将文件发送到我的 Nodejs 服务器FormData 但由于某种原因 节点从未收到它 另外 我怎样才能让节点在页面上发回一条确认消息 说明已收到文件 我做错了什么或错过了什么 请帮忙 先感谢
  • 如何检查当前页面是否是WordPress中的插件管理面板

    我想知道如何检查我当前是否位于插件的管理页面 我创建了一个带有菜单项的插件 该菜单项显示一个包含该插件使用的一些统计信息的页面 为此 我使用自定义 JQuery 插件和一些 CSS 我永远不会在该页面之外使用它们 所以我想知道如何检查这个
  • 使用扩展 DefaultBatchConfiguration 的编程方式时未创建 Spring Batch 5 和 Spring Boot 3 元数据表

    当使用编程方式扩展时DefaultBatchConfiguration 即使属性spring batch jdbc initialize schema被设定为always 有没有办法在扩展时启用自动模式初始化DefaultBatchConf
  • 重新打开时 CSV 中的前导零[重复]

    这个问题在这里已经有答案了 我有 txt 文件 如下所示 我正在使用显示的方法在excel中导入txt文件here http www upenn edu computing da bo webi qna iv csvLeadingZeros
  • 我们可以在基本 Clear Case 项目的配置规范中省略元素 * /main/LATEST 吗?

    在我拥有的一个基本的透明案例项目中 交给我的配置规范如下所示 element CHECKEDOUT element PROJ 1 5 0 LATEST element main LATEST mkbranch PROJ 1 5 0 elem
  • 如何在Mule中创建独占队列消费者?

    在 ActiveMQ 中 您可以为队列配置独占消费者 例如 Queue Name Here consumer exclusive true 如何在 Mule 中配置像上面这样的独占消费者 您需要对队列名称进行 URL 编码 因为 Mule
  • 在 Go 中添加迄今为止的天数

    我正在尝试向 Go 中的现有日期添加天数 实际上是几周 我努力了myDate Add time Hour 24 7 weeksToAdd 但是当我尝试构建时出现错误 invalid operation time Hour startAdd
  • Spring Boot在启动时使用构造函数参数初始化bean

    我需要初始化以下内容PointQuadTree使用带有构造函数参数的 Spring Boot 在启动时使用类 并使该对象在整个应用程序中可用 构造函数参数 minX maxX 需要来自 application properties 文件 点
  • Symfony2 表单:创建新表单或选择现有表单

    我有一个实体 A 它将 oneToMany 与实体 B 相关联 我希望用户可以选择从现有 B 实体中进行选择 或者在 A 类型的表单上创建一个新实体 到目前为止 我的表单上有以下内容 gt add ExistingB entity arra
  • 缩放 Windows 窗体

    基本上 我希望在通过拖动调整 WindowsForm 大小时 所有内容 控件等 都能随 WindowsForm 一起缩放 以便用户可以自己确定 UI 的大小 图片并不完美 但我希望它能解释这一点 最简单的方法是使用 Flow Table L
  • 从 PixelFormat 获取像素长度

    我如何获取像素长度 以字节为单位 像素格式 http msdn microsoft com en us library system drawing imaging pixelformat aspx枚举 我想使用本机方法处理图像像素 但是如
  • 类型错误:必须是 pygame.Surface,而不是元组。 Python/Pygame 菜鸟

    堆栈溢出的用户您好 我已经编写了这段代码 它会在您单击 pygame 屏幕时绘制线条 但是当我运行该程序时 我收到一条错误消息 TypeError must be pygame Surface not tuple 我试图搞乱这个程序 但我没
  • Python:从文件创建列表

    因此 我尝试创建一个函数来打开一个文本文件 逐行读取它 然后获取从中提取的数据来创建一个列表 def file open filename str input enter file name for perk py to sort thro
  • 轮询和事件驱动编程是同一种技术的不同说法吗?

    我研究了中断与循环轮询 并了解了不必等待轮询的中断的优点 在我看来 轮询就像事件驱动的编程 或者至少类似于侦听器 而轮询的作用实际上很像侦听输入或输出 您同意还是我误解了轮询 循环监听 和事件驱动编程 也用所谓的监听器监听 之间的任何关键区
  • C++ 变体访问重载函数

    我想在变体上执行重载函数 以下代码块可以工作并编译 但是visit调用似乎过于复杂 为什么我不能简单地写 std visit f something 工作版本和上下文 include