作为 C++ 模板参数的类似函数签名的表达式

2023-12-13

我在看唐·克拉格斯顿的快速委托迷你库并注意到一个奇怪的语法技巧,其结构如下:

TemplateClass< void( int, int ) > Object;

看起来好像函数签名被用作模板实例声明的参数。

这项技术(其在 FastDelegate 中的存在显然是由乔迪·哈金斯 (Jody Hagins) 发明的)用于简化具有半任意数量的模板参数的模板实例的声明。

也就是说,它允许这样的事情:

// A template with one parameter
template<typename _T1>
struct Object1
{
    _T1 m_member1;
};

// A template with two parameters
template<typename _T1, typename _T2>
struct Object2
{
    _T1 m_member1;
    _T2 m_member2;
};

// A forward declaration
template<typename _Signature>
struct Object;

// Some derived types using "function signature"-style template parameters
template<typename _Dummy, typename _T1>
struct Object<_Dummy(_T1)> : public Object1<_T1> {};

template<typename _Dummy, typename _T1, typename _T2>
struct Object<_Dummy(_T1, _T2)> : public Object2<_T1, _T2> {};

// A. "Vanilla" object declarations
Object1<int> IntObjectA;
Object2<int, char> IntCharObjectA;

// B. Nifty, but equivalent, object declarations
typedef void UnusedType;
Object< UnusedType(int) > IntObjectB;
Object< UnusedType(int, char) > IntCharObjectB;

// C. Even niftier, and still equivalent, object declarations
#define DeclareObject( ... ) Object< UnusedType( __VA_ARGS__ ) >
DeclareObject( int ) IntObjectC;
DeclareObject( int, char ) IntCharObjectC;

尽管确实有点黑客行为,但我发现这种对可变参数模板参数的欺骗性模拟相当令人兴奋。

这个技巧的真正要点似乎是我可以将诸如“Type1(Type2, Type3)”之类的文本结构作为参数传递给模板。所以这是我的问题:编译器到底如何解释这个结构?它是函数签名吗?或者,它只是一个带有括号的文本模式?如果是前者,那么这是否意味着就模板处理器而言,任何任意函数签名都是有效类型?

后续问题是,既然上面的代码示例是有效的代码,为什么 C++ 标准不允许您执行如下所示的操作,但该操作无法编译?

template<typename _T1>
struct Object
{
    _T1 m_member1;
};

// Note the class identifier is also "Object"
template<typename _T1, typename _T2>
struct Object
{
    _T1 m_member1;
    _T2 m_member2;
};

Object<int> IntObject;
Object<int, char> IntCharObject;

关于你的第一个问题 - 关于类型int(char, float)- 这是一个有效的 C++ 类型,并且是接受 a 的函数的类型char and a float并返回一个int。请注意,这是实际函数的类型,而不是函数指针,函数指针将是int (*) (char, float)。任何函数的实际类型都是这种不寻常的类型。例如,类型

void DoSomething() {
    /* ... */
}

is void ().

在例程编程中这种情况很少出现的原因是,在大多数情况下您无法声明这种类型的变量。例如,以下代码是非法的:

void MyFunction() { 
    void function() = DoSomething; // Error!
}

然而,您确实看到使用函数类型的一种情况是传递函数指针:

void MyFunction(void FunctionArgument()) {
     /* ... */
}

更常见的是,这种函数被编写为接受函数指针,但接受函数本身是完全可以的。它是在幕后制作的。

至于你的第二个问题,为什么用不同数量的参数编写相同的模板是非法的,我不知道规范中禁止它的确切措辞,但它与以下事实有关:一旦你声明了一个类模板,您不能更改它的参数数量。但是,您可以对具有不同数量参数的模板提供部分专业化,当然前提是部分专业化仅对原始参数数量进行专业化。例如:

template <typename T> class Function;
template <typename Arg, typename Ret> class Function<Ret (Arg)> { 
    /* ... */
};

Here, Function始终采用一个参数。模板特化接受两个参数,但特化仍然仅针对一种类型(具体来说,Ret (Arg)).

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

作为 C++ 模板参数的类似函数签名的表达式 的相关文章

  • 进程何时获得 SIGABRT(信号 6)?

    C 中进程获得 SIGABRT 的场景有哪些 该信号是否始终来自进程内部 或者该信号可以从一个进程发送到另一个进程吗 有没有办法识别哪个进程正在发送该信号 abort 向调用进程发送SIGABRT信号 就是这样abort 基本上有效 abo
  • 在搜索 List 时,为什么 Enumerable.Any(Func predicate) 比带有 if 语句的 foreach 慢

    最近有件事引起了我的好奇心 Why is the Enumerable Any Func
  • 我的线程图像生成应用程序如何将其数据传输到 GUI?

    Mandelbrot 生成器的缓慢多精度实现 线程化 使用 POSIX 线程 Gtk 图形用户界面 我有点失落了 这是我第一次尝试编写线程程序 我实际上并没有尝试转换它的单线程版本 只是尝试实现基本框架 到目前为止它是如何工作的简要描述 M
  • 32 位应用程序的特征最大矩阵大小

    所以 我正在寻找Eigen http eigen tuxfamily org index php title Main Page当我尝试声明大于 10000x10000 的矩阵时 包崩溃 我需要声明一个像这样的矩阵 可靠地大约有 13000
  • C# 中的接口继承

    我试图解决我在编写应用程序时遇到的相当大的 对我来说 问题 请看这个 为了简单起见 我将尝试缩短代码 我有一个名为的根接口IRepository
  • POCO HTTPSClientSession 发送请求时遇到问题 - 证书验证失败

    我正在尝试使用 POCO 库编写一个向服务器发出 HTTPS 请求的程序 出于测试目的 我正在连接到具有自签名证书的服务器 并且我希望允许客户端进行连接 为了允许这种情况发生 我尝试安装InvalidCertificateHandler这是
  • 暂停下载线程

    我正在用 C 编写一个非常简单的批量下载程序 该程序读取要下载的 URL 的 txt 文件 我已经设置了一个全局线程和委托来更新 GUI 按下 开始 按钮即可创建并启动该线程 我想要做的是有一个 暂停 按钮 使我能够暂停下载 直到点击 恢复
  • 在 2D 中将一个点旋转另一个点

    我想知道当一个点相对于另一个点旋转一定角度时如何计算出新的坐标 我有一个块箭头 想要将其相对于箭头底部中间的点旋转角度 theta 这是允许我在两个屏幕控件之间绘制多边形所必需的 我无法使用和旋转图像 从我到目前为止所考虑的情况来看 使问题
  • Qt 创建布局并动态添加小部件到布局

    我正在尝试在 MainWindow 类中动态创建布局 我有四个框架 它们是用网格布局对象放置的 每个框架都包含一个自定义的 ClockWidget 我希望 ClockWidget 对象在调整主窗口大小时相应地调整大小 因此我需要将它们添加到
  • C# 中条件编译符号的编译时检查(参见示例)?

    在 C C 中你可以这样做 define IN USE 1 define NOT IN USE 1 define USING system 1 system 1 IN USE 进而 define MY SYSTEM IN USE if US
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 当模板类不包含可用的成员函数时,如何在编译时验证模板参数?

    我有以下模板struct template
  • 如何挤出平面 2D 网格并赋予其深度

    我有一组共面 连接的三角形 即二维网格 现在我需要将其在 z 轴上挤出几个单位 网格由一组顶点定义 渲染器通过与三角形数组匹配来理解这些顶点 网格示例 顶点 0 0 0 10 0 0 10 10 0 0 10 0 所以这里我们有一个二维正方
  • 有没有一种简单的方法可以让 Visual Studio 2015 使用特定的 ToolsVersion?

    使用特定版本构建项目或解决方案时msbuild我可以使用以下命令选择早期的 net 工具链 toolsversion or tv switch C Program Files x86 MSBuild 14 0 bin msbuild tv
  • 在类的所有方法之前运行一个方法

    在 C 3 或 4 中可以做到这一点吗 也许有一些反思 class Magic RunBeforeAll public void BaseMethod runs BaseMethod before being executed public
  • 当前的 x86 架构是否支持非临时加载(来自“正常”内存)?

    我知道有关此主题的多个问题 但是 我没有看到任何明确的答案或任何基准测量 因此 我创建了一个处理两个整数数组的简单程序 第一个数组a非常大 64 MB 第二个数组b很小 无法放入 L1 缓存 程序迭代a并将其元素添加到相应的元素中b在模块化
  • strcmp 给出分段错误[重复]

    这个问题在这里已经有答案了 这是我的代码给出分段错误 include
  • 剪贴板在 .NET 3.5 和 4 中的行为有所不同,但为什么呢?

    我们最近将一个非常大的项目从 NET Framework 3 5 升级到 4 最初一切似乎都工作正常 但现在复制粘贴操作开始出现错误 我已经成功制作了一个小型的可复制应用程序 它显示了 NET 3 5 和 4 中的不同行为 我还找到了一种解
  • 什么是 __declspec 以及何时需要使用它?

    我见过这样的例子 declspec在我正在阅读的代码中 它是什么 我什么时候需要使用这个构造 这是 Microsoft 对 C 语言的特定扩展 它允许您使用存储类信息来赋予类型或函数属性 文档 declspec C https learn
  • 使用 Crypto++ 获取 ECDSA 签名

    我必须使用 Crypto 在变量中获取 ECDSA 签名 我在启动 SignMessage 后尝试获取它 但签名为空 我怎样才能得到它 你看过 Crypto wiki 吗 上面有很多东西椭圆曲线数字签名算法 http www cryptop

随机推荐

  • 防止浏览器在提交表单时跳转到首页

    我试图防止用户提交表单时页面跳转到顶部 有很多人建议return false 但是 它也阻止了表单的提交 我想知道是否有人可以帮助我 JQuery submit click function doesn t work return fals
  • 收据打印机 - 从网页打印

    我有一台收据打印机 它连接到我的计算机上的串行 COM1 我正在尝试从网页打印收据 当打印时 它只是一个空白 没有任何文本 空白收据 它在 IE8 上工作正常 但在 Firefox 3 6 上不起作用 我有一台 Epson TM T88II
  • Stream.Seek(0, SeekOrigin.Begin) 或 Position = 0

    当您需要将流重置为开始时 例如MemoryStream 是使用的最佳实践 stream Seek 0 SeekOrigin Begin or stream Position 0 我发现两者都工作得很好 但想知道其中一个是否比另一个更正确 U
  • 将带有内部链接的 Excel 转换为 pdf

    我正在尝试将带有内部链接 即指向同一 Excel 中不同位置的链接 的 Excel 转换为 pdf 我已经浏览了网上关于这方面的几篇文章 但似乎找不到任何适当的解决方案来进行这种转换 提供的解决方案主要适用于外部超链接 而不适用于内部超链接
  • 如何发出帖子请求来创建新用户

    我正在使用react chat engine 创建一个聊天应用程序 一切都运转良好 除了我不知道如何发出帖子请求来创建新用户这一事实 这是我的代码 const handelSubmit async e gt e preventDefault
  • eclipse无需jdk运行程序

    为什么我们不需要安装jdk就可以在eclipse中编译执行java程序呢 jre安装就足够了 但是在从cmd运行代码时我们需要安装jdk eclipse 是否附带任何替代 javac 我尝试在 eclipse 文件夹中搜索 javac 但没
  • 如何使用带参数的嵌套命令创建 Git 别名?

    在我的点文件中 我有以下有效的函数 function undelete git checkout git rev list n 1 HEAD 1 1 我这样使用 undelete path to deleted file txt 我想确定这
  • 查找列表中的第一个元素和索引匹配条件

    考虑这个简单的例子 mylist 1 2 3 4 5 6 for idx el in enumerate mylist if el gt 0 myidx myel idx el break myidx myel Out 20 2 3 我感兴
  • SQL Server 获取前三条记录的值并按每人一行显示

    我试图将一个人的前三行的值全部显示在一行中 我的数据如下所示 id co number client no Client name taken date taken value 270103 12 1111 John Doe 6 7 11
  • 使用 Android Espresso 从仅包含图标的 TabLayout 中单击 Tab 后检查片段可见性

    我正在尝试从已使用视图寻呼机设置的 tabLayout 中单击选项卡后检查我的片段是否可见 这是我的实际活动代码 位于我的活动 onCreate 方法中 mViewPager findViewById R id contentFrameLa
  • 检测添加到 DOM 的图像何时已加载

    比如说 用户打开一个页面 单击一个按钮 然后出现带有图像的弹出窗口 如何检测所有图像何时已加载 我不能使用window onload在这里 因为页面已经加载了所有资源 为了说清楚 我想找出弹出窗口的最终范围 弹出窗口添加到 DOM 中 如下
  • 将 AST 编译回源代码

    我目前正在构建一个用 PHP 编写的 PHP 解析器 因为没有现有的解析器出现我之前的问题 The 解析器本身效果相当好 现在显然解析器本身没有什么好处 除了静态分析 我想对 AST 应用转换 然后将其编译回源代码 应用转换并不是什么大问题
  • jquery getJSON 不适用于 url

    我找到了用于实时显示分数的 json url http json cricket appspot com score json json的输出 batting team Canada date Feb 28 2011 match Canad
  • 有没有流行的 C# 库来运行 HTTP?例如简化使用 httpwebrequest 等[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 有没有流行的 C 库来运行
  • 在 Java 中如何更改或设置默认打印机

    我知道如何获取可用打印机的列表 我希望用户能够从列表中进行选择并将其设置为会话的默认打印机 使用Windows 7 我知道这很容易完成我只想创建一个简单的java程序 a 增长知识 b 这里的老师非常不喜欢玩印刷属性 感谢您提前的帮助 您知
  • 调试 Terraform AWS 应用程序负载均衡器验证错误的最佳方法是什么?

    我尝试使用 Terraform 在 AWS 上配置演示 Web 服务 但遇到以下错误 Error Error applying plan 2 error s occurred module prod module web module we
  • C#:如何在此 keydown 事件中显示修饰键名称 + 非修饰键名称?

    我使用此代码来检测文本框的 KeyDown 事件中是否按住了修饰键 private void txtShortcut KeyDown object sender KeyEventArgs e if e Shift e Control e A
  • 使用Matlab的ocr进行文本识别

    我正在尝试对这张图片进行 OCR 这就是我正在做的使用ocr of MATLAB I imread N jpg r ocr I TextLayout Word 但不是得到N as Text这就是我得到的 r ocrText with pro
  • Android 11 - Kiosk 模式锁屏 NFC 问题

    我有一个使用 Android Management API 作为信息亭运行的应用程序 我的一些客户更喜欢使用 MDM 平台 例如 Intune 和 Airwatch 我们将 Samsung XCover 系列用于我们的专用设备 Androi
  • 作为 C++ 模板参数的类似函数签名的表达式

    我在看唐 克拉格斯顿的快速委托迷你库并注意到一个奇怪的语法技巧 其结构如下 TemplateClass lt void int int gt Object 看起来好像函数签名被用作模板实例声明的参数 这项技术 其在 FastDelegate