如何检索 C99 可变参数宏的最后一个参数?

2024-04-15

Visual Studio 失败的 static_assert 错误消息完全由错误代码和 static_assert 的第二个参数组成,没有任何其他消息表明这是静态断言失败。我想做一个宏来解决这个问题。例如,作为第一次尝试:

#define STATIC_ASSERT(x) static_assert(x, "static assertion failed: " #x)

您遇到的第一个问题是 C 预处理器不理解< >作为封闭分隔符,这会导致模板出现语法错误。以下行为将成为非法:

template <typename T, typename U>
auto SafeMultiply(T x, U y) -> decltype(x * y)
{
    STATIC_ASSERT(std::is_same<T, U>::value);
    STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
    if (x > (std::numeric_limits<decltype(x * y)>::max)())
        throw std::overflow_error("multiplication overflow");
    return x * y;
}

这是非法的,因为第一个 T 和 U 之间的逗号STATIC_ASSERT被解释为分隔两个宏参数,而不是模板参数。 C 预处理器会抛出错误,因为STATIC_ASSERT宏只接受一个参数。

该问题的两个主要解决方案是使用双括号,以及最近使用的可变参数宏:

// Invoke the macro this way...
STATIC_ASSERT((std::is_same<T, U>::value));
// ...or define it this way:
#define STATIC_ASSERT(...) static_assert((__VA_ARGS__), \
    "static assertion failed: " #__VA_ARGS__)

后一种解决方案更好,只需更改宏定义即可。 (多余的括号__VA_ARGS__新定义中的目的是在一些更奇怪的情况下保留正确的操作顺序。在这个特定的宏中这可能并不重要,但在宏定义中将括号括起来是一个好习惯。)

现在如果我想改变我的STATIC_ASSERT像标准 C++ 一样获取消息的宏static_assert,但要在消息中添加前缀?有点像这样,但支持使用std::is_same<T, U>不使用双括号:

// Causes a syntax error :(
#define STATIC_ASSERT(expr, msg) static_assert((expr), \
    "static assertion failed: " msg)
STATIC_ASSERT(std::is_same<T, U>, "x and y are not of the same type");

如果我可以获得可变参数宏的最后一个参数,它就会起作用:

// I wish this'd work
#define STATIC_ASSERT(..., msg) static_assert((__VA_ARGS__), \
    "static assertion failed: " msg)
STATIC_ASSERT(std::is_same<T, U>, "x and y are not of the same type");

但由于这是不合法的,我如何合法地获取 a 的最后一个参数...宏参数设置?当然,我可以颠倒参数顺序,但它与static_assert.


在完全一般的情况下,没有简单的方法来获取最后一个宏参数,但是您可以轻松实现一个版本,该版本可以获取参数列表的最后一个元素,达到某个预定的最大值。对于现实世界的代码来说,像 64 个参数这样的参数通常就足够了。

您需要做的就是计算传递的参数数量,然后返回元素N-1从列表中:

// count arguments
#define M_NARGS(...) M_NARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define M_NARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N

// utility (concatenation)
#define M_CONC(A, B) M_CONC_(A, B)
#define M_CONC_(A, B) A##B

#define M_GET_ELEM(N, ...) M_CONC(M_GET_ELEM_, N)(__VA_ARGS__)
#define M_GET_ELEM_0(_0, ...) _0
#define M_GET_ELEM_1(_0, _1, ...) _1
#define M_GET_ELEM_2(_0, _1, _2, ...) _2
#define M_GET_ELEM_3(_0, _1, _2, _3, ...) _3
#define M_GET_ELEM_4(_0, _1, _2, _3, _4, ...) _4
#define M_GET_ELEM_5(_0, _1, _2, _3, _4, _5, ...) _5
#define M_GET_ELEM_6(_0, _1, _2, _3, _4, _5, _6, ...) _6
#define M_GET_ELEM_7(_0, _1, _2, _3, _4, _5, _6, _7, ...) _7
#define M_GET_ELEM_8(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) _8
#define M_GET_ELEM_9(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) _9
#define M_GET_ELEM_10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) _10

// Get last argument - placeholder decrements by one
#define M_GET_LAST(...) M_GET_ELEM(M_NARGS(__VA_ARGS__), _, __VA_ARGS__ ,,,,,,,,,,,)

您可以通过几分钟的复制和粘贴将其扩展到您想要的有限数量。

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

如何检索 C99 可变参数宏的最后一个参数? 的相关文章

  • 如何获取正在访问 ASP.NET 应用程序的当前用户?

    为了获取系统中当前登录的用户 我使用以下代码 string opl System Security Principal WindowsIdentity GetCurrent Name ToString 我正在开发一个 ASP NET 应用程
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new

随机推荐

  • rspec - 为什么仅在 ubuntu 上,当它们相同时,使用 assert_equal 进行此属性比较会失败?

    两个测试都失败了 但仅在 Ubuntu 12 上失败 但在我的 新 Mac 上却失败了 失败的两个是 Active Record 对象属性比较 但我尽了最大努力来比较它们 例如在命令行创建哈希并粘贴属性 比较表明它们是相同的 这是一个真正的
  • Airflow initdb slot_pool 不存在

    我面临一个问题airflowpostgres 后端初始化 乌班图 18 04 1 气流 v1 10 6 Postgres 10 10 Python 3 6 当我跑步时 airflow initdb I get 2019 11 22 10 1
  • 在本例中如何避免 VBA 中的 select/active 语句?

    需要导出一个PDF文件中的所有工作表 所以我找到了这段代码 它有效 导出一个PDF 每张工作表一个页面 但我不想使用 select active 语句 我更喜欢使用存储对象的变量 问题 如何避免此代码中的 select ActiveShee
  • WPF MVVM 可观察集合不更新 GUI

    我正在设计一个 MVVM WPF 应用程序 并且有一个 ViewModel 它有一个名为 SelectedCustomer 的属性 类型为 Customer 该对象有一个名为 SummaryDetails 的 ObservableColle
  • 如何在 GWT 的 Jetty 中启用 HTTPS?

    如何在 GWT 附带的 Jetty 中启用 HTTPS gwt dev jar 中 隐藏 了一个 README SSL txt 你可以找到最新版本在 Github 上 https github com gwtproject gwt blob
  • (Fortify) 类别:Android 不良做法:缺少 Google Play 服务更新的安全提供程序(1 期)

    我们正在使用 Fortify 扫描我的 Android 源代码 但我无法摆脱这个问题 类别 Android 不良做法 缺少 Google Play 服务更新的安全提供程序 1 期 Fortify指向这行代码 工具 替换 android al
  • Numpy 沿特定维度选择不替换

    在不进行替换的情况下 我根据指定的分布从样本中 n 次不同地选择 k 个元素 迭代解决方案很简单 for in range n np random choice a size k replace False p p 我无法设置size k
  • Java:如何通过忽略“\n”来逐行读取文件

    我正在尝试读取每行制表符分隔的文本文件行 行通过使用回车符 r n 进行分隔 并且在制表符分隔的文本字段中允许使用换行符 n 由于我想每行读取文件行 因此我希望我的程序忽略独立的 n 很遗憾 BufferedReader使用这两种可能性来分
  • std::this_thread::yield 与 Linux 上的 sched_yield 有什么不同吗?

    我只是想知道如何std this thread yield是在linux上实现的 它与sched yield 我见过一些自旋锁的实现 这意味着std this thread yield是更轻量级的东西sched yield就线程放弃进程多长
  • OSGi 应用程序修补策略

    修补 OSGi 容器的适当机制是什么 1 Should the bundles binaries jars have the same name as the old ones then a Replace the bundle with
  • 使用多线程的 JPA 中的事务

    我的目标是使用单元测试在我的应用程序中引发乐观锁定异常 我已经在理论上了解了如何做到这一点 但我在实践中的问题是如何维护两个线程之间的事务 所以 这就是我到目前为止所做的 我正在使用 JUnit 测试 RunWith SpringJUnit
  • 用于进行修改的 git 工作流程,您永远不会将其推回原点

    我正在构建一个 iPhone 应用程序PhoneGap http phonegap com 其中有一个 Git 存储库 我想在我自己的 Git 存储库中跟踪对 PhoneGap 代码的更改 主要是向 www 目录添加文件 同时能够从 Pho
  • GitHub、Gerrit、Hudson(Jenkins) 工作流程

    我刚刚开始一起使用 GitHub Gerrit 和 Hudson Jenkins 我需要一些关于工作流程的想法 我们想使用 GitHub 作为我们的主要远程存储库 我们希望主要使用 Gerrit 进行代码审查 但也用于 Hudson 中的构
  • 如何运行 Webpack 开发服务器 --https --hot --inline

    使用 CLI 配置时 有没有办法在 https 上运行 webpack dev server 问题是连接到socket io结束了http并不是https 存在解决方法 但非常烦人 手动包含https webpack dev server在
  • Scala - 以函数方式修改字符串

    我刚刚开始使用 Scala 因此开始以更实用的方式做事 只是想知道是否有一种更实用的方法来实现如下所示的功能 def expand exp String String var result exp for k v lt libMap res
  • Python/Django 中的音频波形可视化

    我已经在 Stack Overflow 上寻找这个问题的答案 但似乎没有地方给出正确的答案或方向 我的项目将允许用户上传 WAV 最终将在服务器上使用 FFmpeg 将其转换为低质量 MP3 并将全部存储在 Amazon S3 上并提供服务
  • asp.net mvc - ActionLink 的渲染不一致

    我有一个控制器 它接受以下两种格式的 URL 网络 添加或编辑 gt 在页面上呈现空白表单以添加新的网络对象 网络 AddOrEdit id gt 使用预填充表单呈现页面以编辑网络对象 带有 ID id 显然 每个实例中都使用相同的视图 我
  • 在 JavaScript 中逐行动态添加字幕到视频元素

    我想知道目前是否可行 下面是我的 HTML
  • Chrome DevTools 中缺少“添加到主屏幕”链接

    使用 Google 服务可能会令人沮丧 他们有令人难以置信的文档 但文档总是假设一切正常 如果有什么东西不像广告上说的那样有效 那你就完全靠自己了 没有错误消息 没有解决问题的帮助 甚至没有承认某些事情可能不起作用 以防万一 添加到主屏幕
  • 如何检索 C99 可变参数宏的最后一个参数?

    Visual Studio 失败的 static assert 错误消息完全由错误代码和 static assert 的第二个参数组成 没有任何其他消息表明这是静态断言失败 我想做一个宏来解决这个问题 例如 作为第一次尝试 define S