在编译时构建类型列表 - 无 C++11

2024-05-15

我想做准确的this https://stackoverflow.com/a/18704609/2566773获取类型/类的列表。但我不能使用 C++11。有什么建议如何将类型附加到模板列表吗?

编辑:我想做的一些代码:

#include <iostream>
#include <typeinfo>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/for_each.hpp>

using namespace std;

class A {};
class B {};
class C {};

typedef boost::mpl::vector<> type1;
// supposed I'd like to have this as a #define macro so someone can call
// REGISTER_CLASS(A) and push the type into a list
typedef boost::mpl::push_back<type1, A> type2;
typedef boost::mpl::push_back<type2, B> type3;
typedef boost::mpl::push_back<type3, C> type4;

template <typename T> struct wrap {};

struct Print
{
      template <typename T> void operator()( wrap<T> t ) const
      {
            cout << typeid( T ).name() << endl;
      }
};

int main()
{
      // this doesn't compile because type4 is a sequence of sequence
      // supposed, I need to "flatten" this list so it's eqv to vector<A,B,C>
      boost::mpl::for_each<type4, wrap<boost::mpl::placeholders::_1> >( Print() );

      // second problem is that I'd like to have typedef of 1 typelist only, not
      // type1, type2, ... typeN, since I don't know the exact number of classes

      return 0;
}

首先,代码无法编译的实际问题是您正在对操作进行类型定义,而不是对它们的结果进行类型定义。像这样改变它:

typedef boost::mpl::push_back<type1, A>::type type2;
typedef boost::mpl::push_back<type2, B>::type type3;
typedef boost::mpl::push_back<type3, C>::type type4;

现在更全面地了解为什么需要 typedef。

使用元编程技术(如您的情况中的模板元编程)需要心理“转变”,因为范式与“正常”C++ 不同。 C++本身就是一个至关重要的语言。元程序是功能性的.

就数据结构而言,函数范式意味着数据结构是总是一成不变的。例如,在命令式语言中,您可以这样做:

vector<int> v;
v.push(4);
v.push(7);
v.push(42);
process(&v);
print(v);

在函数式语言中,等效的代码是:

v = vector<int>;
v1 = v.push(4);
v2 = v1.push(7);
v3 = v2.push(42);
v4 = process(v3);
print(v4);

或者,使用更函数式的表示法,如下所示:

print(process(vector<int>().push(4).push(7).push(42)));

在纯函数式(LISP 风格)表示法中,它将是:

(print (process (push (push (push (vector<int>) 4) 7) 42)))

另一种说法是,在函数式语言中,数据结构不是stored,他们是产生的。

回到 C++ 模板元编程和 Boost.MPL,这意味着附加类型的唯一方法T到类型列表(MPL 向量)v是要通过boost::mpl::push_back<v, T>::type在那里你想要处理“向量”T推回“。以维持DRY http://en.wikipedia.org/wiki/Don%27t_repeat_yourself,您通常使用“向量”的 typedef 来执行此操作T推后。”


不幸的是,这意味着没有办法创建一个REGISTER_CLASS按照您想要的方式进行宏操作。您可以通过更多元编程(包括使用 Boost.Preprocessor)来制作类似的东西。

这个想法是使用 Boost.Preprocessorslot保存类型列表的最后一个标识符。而不是调用REGISTER_CLASS直接宏,那就是#included,类名通过另一个宏传递。像这样的事情:

内部寄存器.hpp

//This file MUST NOT have include guards

#ifndef CLASS_TO_REGISTER
  #error You must define CLASS_TO_REGISTER before executing REGISTER_CLASS()
#endif

typedef boost::mpl::push_back<
  CURRENT_TYPELIST(),
  CLASS_TO_REGISTER
>::type BOOST_PP_CAT(registered, BOOST_PP_INC(BOOST_PP_SLOT(1)));

#undef CLASS_TO_REGISTER

#define BOOST_PP_VALUE BOOST_PP_SLOT(1) + 1
#include BOOST_PP_ASSIGN_SLOT(1)

注册.hpp

typedef boost::mpl::vector<>::type registered0;

#define BOOST_PP_VALUE 0
#include BOOST_PP_ASSIGN_SLOT(1)

#define REGISTER_CLASS() "internal_register.hpp"

#define CURRENT_TYPELIST() BOOST_PP_CAT(registered, BOOST_PP_SLOT(1))

main.cpp(或任何其他用法):

#include "registration.hpp"

class A {};
class B {};
class C {};

#define CLASS_TO_REGISTER A
#include REGISTER_CLASS()

#define CLASS_TO_REGISTER B
#include REGISTER_CLASS()

#define CLASS_TO_REGISTER C
#include REGISTER_CLASS()

template <typename T> struct wrap {};

struct Print
{
      template <typename T> void operator()( wrap<T> t ) const
      {
            cout << typeid( T ).name() << endl;
      }
};

int main()
{
      boost::mpl::for_each<CURRENT_TYPELIST(), wrap<boost::mpl::placeholders::_1> >( Print() );

      return 0;
}

当涉及多个翻译单元时,需要进行更多调整才能正常工作(在这种情况下,有些事情根本无法完成,如果将适当的标识符放入匿名命名空间中,则可以完成有些事情)。但它应该作为一个起点。

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

在编译时构建类型列表 - 无 C++11 的相关文章

  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • 在 Xamarin Android 中将图像从 URL 异步加载到 ImageView 中

    我有一个包含多个项目的 ListView 列表中的每个项目都应该有一个与之关联的图像 我创建了一个数组适配器来保存每个列表项并具有我希望加载的图像的 url 我正在尝试使用 Web 请求异步加载图像 并设置图像并在加载后在视图中更新它 但视
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • Angular 2 ngModel 不工作(仅限 javascript)

    所以我是 Angular2 javascript 的新手 我能够通过 5 分钟的 Angular 教程制作一个简单的 Hello world 我对 Angular2 的新变化很好奇 我开始阅读 Angular2 Js 文档 但我发现它不完整
  • CGContextSelectFont 等效项

    在 iOS 7 CGContext SelectFont 中已弃用 已弃用的消息说我必须使用 Core Text 但我不知道哪一个与这段代码完全相同 CGContextSelectFont context Helvetica kBarLab
  • 我是否需要安装 SQLite 才能使 SQLiteJDBC 正常工作?

    我想我只是没有 明白 如果我的计算机上尚未安装 SQLite 并且我想编写一个使用嵌入式数据库的 Java 应用程序 并且我将 SQLiteJDBC JAR 下载 导入到我的项目中 那么这就是我所需要的吗 或者 我是否需要先安装 SQLit
  • 在 YAML 中使用占位符

    有没有办法在 YAML 中使用占位符 如下所示 foo FOO lt
  • R:根据元素长度从向量中删除元素

    如何根据字符串的字符数或长度从字符串向量中删除元素 df lt c asdf fweafewwf af aewfawefwef awefWEfawefawef gt df 1 asdf fweafewwf af aewfawefwef aw
  • tar 和 zip 有什么区别? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 tar 和 zip 有什么区别 每个的用例是什么 tar其本身只是将文件捆绑在一起 结果称为tarball 尽管zip也应用压缩 通常你使用gzip随
  • Facebook-API 中的会话密钥和访问令牌

    有人可以向我解释一下什么是会话密钥和访问令牌吗 怎样才能抓住那两个人呢 为什么以及何时需要使用它们 什么时候是 一次性 什么时候不是 另外 他们之间有什么区别 请用Java 来做 我是一位刚接触 facebook API 的 Java 开发
  • iPad 横向触摸开始变得混乱

    我的应用程序仅允许在横向方向上使用 并且它以横向方式启动 因此 iPad 横向时左上角为 0 0 因此一切正常 但是 当我拿起 touchesBegan 时 它无法正常工作 只有当我点击 iPad 的右侧三分之二时 它才会接收到触摸 我知道
  • 通过 PHP 连接到 socket.io(nodejs)

    我需要通过 php 连接到 websocket 发送数据并立即断开连接 无需等待套接字的响应 我用了大象io http elephant io 但更新库后不起作用 请告诉我如何通过 PHP 连接到 websocket 我也遇到了这个问题 学
  • 无法添加钥匙串项目。使用 KeychainItemWrapper 更改标识符后出现错误 - 25299?

    我想用 KeychainItemWrapper 将 UUID 保存在钥匙串中 所以我在中添加以下方法MyKeychainManager m define keychain idenentify com myapp bundle1 void
  • 使用 Java 的 Apache Http 摘要身份验证

    我目前正在开发一个 Java 项目 但无法使 http 摘要身份验证正常工作 我尝试使用 Apache 网站 但没有帮助 我有一个需要 HTTP 摘要身份验证的网站 DefaultHttpClient httpclient new Defa
  • 代表 Git 存储库的数学结构是什么

    我正在学习 Git 如果我能描述一下代表 Git 存储库的数学结构 那就太好了 例如 它是一个有向无环图 它的节点代表提交 它的节点有代表分支等的标签 每个节点最多一个标签 没有标签使用两次 我知道这个描述不正确 我只是想解释我正在寻找的内
  • 为什么 Application.Exit 无法工作?

    我有一个应用程序在取消对话框时出现奇怪的错误 如果该框被取消 应用程序将无法继续 因此它会退出 但由于某种原因它无法工作 因此它会继续运行并崩溃 我调试了这个问题 并且不知何故应用程序在 Application Exit 调用之后运行 我正
  • 视图无法解析为类型

    这里的视图似乎有什么问题 我该如何解决它 错误 视图无法解析为类型 public void onItemClick AdapterView
  • 在Android中使用RxJava2插入SQLiteDatabase

    我在学习RxJava2在安卓中 谁能解释一下我们如何使用将数据插入 SQLiteDatabaseRxJava2 这是我尝试使用的代码示例 但它将数据插入数据库六次 单击时 getCompletableObservable subscribe
  • Netbeans 8.1 Gnome 3 GTK+ UI 字体和选项卡高度

    我刚刚在运行 GNOME 3 桌面的 Ubuntu 16 04 上安装了 NetBeans 8 1 如果可能的话 我想继续使用 IDE 的 GTK 外观和感觉 但 UI 上的字体 尤其是选项卡中的字体 太小且重叠 我尝试添加 fontsiz
  • 有没有办法从主活动中调用另一个自定义适配器内项目的自定义适配器的notifyDataSetChanged()?

    我一直在尝试解决这个问题 但我还没有弄清楚 在我的布局中有一个带有自定义适配器的列表视图 在每个视图中 我都有许多对象存储在名为 ViewHolder 的静态类中 一个是带有另一个自定义适配器的画廊 我的问题是 在我的 Activity 上
  • 需要 RegEx 返回第一段或前 n 个单词

    我正在寻找一个正则表达式来返回段落中的前 n 个单词 或者如果该段落包含少于 n 个单词 则返回完整的段落 例如 假设我最多需要前 7 个单词 p one two p
  • Response.Redirect() 将绝对 URL 作为相对 URL 处理

    我有一个 net C 页面 它重定向到绝对 url 例如 Response Redirect rtsp myvideoServer com myVideoAddress mp4 ticket 1234 dt 1234 但重定向后会导致 ht
  • 在编译时构建类型列表 - 无 C++11

    我想做准确的this https stackoverflow com a 18704609 2566773获取类型 类的列表 但我不能使用 C 11 有什么建议如何将类型附加到模板列表吗 编辑 我想做的一些代码 include