- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试计算调用正确宏的参数数量。连接和参数数量似乎给出了预期的结果,但由于某些原因在 MSVC 上参数数量不起作用。我尝试了已知的修复程序,例如 EXPAND(x) x 和 EXPAND(...) __VA_ARGS__
和 CALL(x,y) x y
但没有任何效果。我还硬编码了一个我知道有效的数字,编译后给出了正确的结果,因此我将问题缩小到计数宏。
编译后 VS 警告没有足够的参数,因为它调用了不正确的 _#_DERIVED(...)
MACRO。
宏
#define CONCAT_DETAIL(l, r) l##r
#define CONCAT(l, r) CONCAT_DETAIL(l, r)
#define _COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define _COUNT(...) _COUNT_N("ignore", ## __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
#define _EXPAND(...) __VA_ARGS__
#define CLASS_BODY(...) CONCAT(_EXPAND(_COUNT(__VA_ARGS__)),_DERIVED)(__VA_ARGS__)
示例用法
CLASS_BODY(Renderer)
CLASS_BODY(Object, XMLParser)
宏编译后的预期结果
_0_DERIVED()
_1_DERIVED(arg1)
_2_DERIVED(arg1, arg2)
.
.
.
最佳答案
MSalters 是对的;带有单下划线的标识符是保留的。如果在实现中包含任何内容时您的宏处于事件状态,它可能会在您最不期望的时候发生冲突。
After compiling VS warns about ...
根据这段引述,我怀疑您是通过尝试编译宏来调试宏。更好的方法是只使用预处理器。在 Microsoft 中,您可以通过在开发控制台的命令行中运行 cl/EP foo.h
来执行此操作(或者在为您的特定实现运行 VCVARSALL
之后)。
现在是宏:
#define _COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define _COUNT(...) _COUNT_N("ignore", ## __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
#define _EXPAND(...) __VA_ARGS__
_COUNT
需要展开一步,否则没用。这样更好:
#define COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define COUNT(...) EXPAND(COUNT_N( , __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0))
#define EXPAND(...) __VA_ARGS__
现在:
COUNT() COUNT(a) COUNT(a,b)
...扩展为:
_1 _1 _2
这技术上是正确的。 COUNT()
有一个参数(它是空的)。这在 Microsoft 中不返回 _0
的原因是因为扩展步骤......这正是允许 COUNT
宏首先工作的原因。如果您希望 COUNT()
返回 0
,您需要添加另一层间接寻址并使用CALL
(因为参数列表需要展开一次以触发逗号省略):
#define COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define COUNT_M(...) EXPAND(COUNT_N( __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0))
#define COUNT(...) CALL(COUNT_M,(, __VA_ARGS__))
#define CALL(X,Y) X Y
#define EXPAND(...) __VA_ARGS__
...现在 COUNT()
返回 _0
;请注意,这是 Microsoft 特有的。
#define CONCAT_DETAIL(l, r) l##r
#define CONCAT(l, r) CONCAT_DETAIL(l, r)
#define COUNT_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define COUNT_M(...) EXPAND(COUNT_N( __VA_ARGS__, _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0))
#define COUNT(...) CALL(COUNT_M,(, __VA_ARGS__))
#define CALL(X,Y) X Y
#define EXPAND(...) __VA_ARGS__
#define CLASS_BODY(...) CONCAT(EXPAND(COUNT(__VA_ARGS__)),_DERIVED)(__VA_ARGS__)
CLASS_BODY()
CLASS_BODY(arg1)
CLASS_BODY(arg1,arg2)
...扩展为:
_0_DERIVED()
_1_DERIVED(arg1)
_2_DERIVED(arg1,arg2)
当然,您现在只是生成以 _
开头的标识符。
关于c++ - 计数 __VA_ARGS__ MSVC 给出意想不到的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46920401/
我有以下两个宏: #define F1(...) [NSString stringWithFormat:__VA_ARGS__] #define F2(format, ...) [NSString s
我想知道##在这个宏定义中做了什么: #define debug(M, ...) fprintf(stderr,M "\n",##__VA_ARGS __) 我在谷歌上搜索了答案,并得出了以下结果。
C++ preprocessor __VA_ARGS__ number of arguments 那里接受的答案对我不起作用。我试过 MSVC++ 10 和 g++ 3.4.5。 我还将示例压缩成更小
此代码片段是否可移植? 定义: #define log(...) std::cout << __FILE__ << "[" << __LINE__ << "]:" \
在可变参数宏中,#__VA_ARGS__是所有参数的逗号分隔字符串(至少我用 gcc 和 clang 得到了这种行为)。有没有一种方法可以在不解析该字符串的情况下为各个参数创建一个字符串数组? 我正在
我有以下宏: #define MY_FCT1( id, ... ) \ FCT( id,__VA_ARGS__ ); \ 我想创建一个新的来做这样的事情: #de
variadic macro提到了 gcc 的 VA_ARGS。 我做了以下实验。 #define EVAL(f,...) eval(f,build_args(args,__VA_ARGS__ , a
我知道我可以做到: #define MACRO(api, ...) \ bool ret = api(123, ##__VA_ARGS__); 这只是一个示例,它是更复杂解决方案的一部分。关键是我
我正在尝试为数组数据冗余编写一个特殊的类型处理。这个想法是在编译时全局定义和声明一个固定大小的数组,但每个声明的数组的大小都不同。这是想法: array[N] = { el1, el2, el3, .
我正在尝试制作一个类似于此的函数: #define printf_copy(s, ...) printf(s, ##__VA_ARGS__) // acceptable! 但这是一个预处理器,我需
如果我尝试编译以下代码: template void Dummy(const TArgs &...args) { } #define DUMMY(...) Dummy("Hello", ##__VA
我想定义一个宏,例如 - #define log(lognumber,...) logreport(lognumber,__VA_ARGS__) 我想检查 __VA_ARGS__ 用户调用 log
假设我们有以下两个函数: void foo1(int p); void foo2(int p, ...); 我想编写一个宏,根据参数的数量自动扩展为正确的宏。我使用了以下肮脏/黑客的方式,但我很好奇是
假设我有一个宏: #define FOO(a, ...) if (a) foo(a, ## __VA_ARGS__) 这很好用: FOO(a)将转换为 if (a) foo(a) FOO(a, )将转
只是为了了解一点背景知识,这不是一个微不足道的练习!我正在使用 Boost.Python,为了避免大量丑陋的样板代码,我使用宏将函数包装在 Python 包装器类中,以选择性地为该方法调用 Pytho
我正在尝试重新定义可变参数宏以使用 cout 而不是 printf。这是原始代码: #define LOGE(...) PRINT_LEVEL(1, __VA_ARGS__); #define P
我正在尝试将 __ VA_ARGS __ 传递给一个函数。由于某种原因,第一个参数总是错误的(看起来像一个地址): #define PRINTF_ERROR(format, ...) {\
我已经从互联网上下载并重新编译了一个库,结果是由于非法指针地址导致核心转储。 查看源码,涉及的语句有: #define E_DEBUG(level, ...) \ if (err_get_de
我正在开发一个嵌入式应用程序,它使用一个库来连接 SPI NAND 内存芯片。提供的库使用打印功能,作为应用程序开发人员,我必须针对我的特定平台覆盖该功能。 例如,他们在代码中广泛使用函数 print
我正在为 SQL 代码使用预处理器宏 va_args hack,以允许直接粘贴到 sqlite3.exe 中以进行快速的非构建调试: #define QUOTE(...) #__VA_ARGS__ c
我是一名优秀的程序员,十分优秀!