简单的问题,我无法在网上找到答案.在可变参数宏中,如何查找参数的数量?如果它有解决方案,我可以使用boost预处理器.
如果它有所不同,我试图转换可变数量的宏参数来增强预处理器序列,列表或数组以进行进一步的重新处理.
我正在研究一个调用宏,
#define CALL(f,...) FN(f)->call((ref(new LinkedList()), __VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)
在被叫时,
CALL(print,2,3,4,5);
Run Code Online (Sandbox Code Playgroud)
将2 3 4 5添加到链接列表(,重载以执行此操作)并调用print,其中需要链接列表按预期工作,但有些调用不需要参数,
CALL(HeapSize);
Run Code Online (Sandbox Code Playgroud)
它仍然需要一个链接列表,但是一个空的,上面不起作用,我试图想出一个宏,它可以使用任何一种风格吗?
编辑:挖掘gcc文档我发现在VA_ARGS之前添加## 会删除,当没有参数但是我无法嵌套宏时,
CALL(print,CALL(HeadSize));
Run Code Online (Sandbox Code Playgroud)
如果我分离它的工作调用,这会导致CALL未定义错误
我知道我可以这样做:
#define MACRO(api, ...) \
bool ret = api(123, ##__VA_ARGS__);
Run Code Online (Sandbox Code Playgroud)
这只是一个例子,它是更复杂的解决方案的一部分.关键是我需要将可变数量的参数附加到第一个123. ##使编译器在123参数之后删除逗号,如果没有参数传递给MACRO.
但现在我想向api附加参数,如下:
#define MACRO(api, ...) \
bool ret = api(__VA_ARGS__##, 456);
Run Code Online (Sandbox Code Playgroud)
诺坎多.一种解决方案是使用两个宏,MACRO和MACRO_V,并使_V版本不处理任何参数.但有没有办法让它与一个宏一起工作?
我有来自第三方C库的可变参数函数:
int func(int argc, ...);
Run Code Online (Sandbox Code Playgroud)
argc表示传递的可选参数的数量.我正在用一个计算参数数量的宏来包装它,如此处所示.为了方便阅读,这里是宏:
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
_61, _62, …Run Code Online (Sandbox Code Playgroud) 我正在使用此帖子中的宏循环遍历我的参数.一切都很棒!但是,有没有办法这两个结合起来CCB_CREATE,并CCB_CREATE_MORE?
我需要提取第一个参数object_type来编写其他代码.附加的object_types将使用FOR_EACH循环插入到地图中.
当我在使用时只有一个参数时,编译器会抱怨CCB_CREATE_MORE(Type1).为了解决这个问题,我制作了另一个宏来处理它CCB_CREATE(Type1).希望找到一个聪明的解决方案,将这两者结合成一个优雅的宏.有任何想法吗?
#define INSERT_LOADER_MAP(object_type) loader_map.insert(make_pair(#object_type, object_type##Loader::loader()))
#define CCB_CREATE_MORE(object_type,...) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
FOR_EACH(INSERT_LOADER_MAP,object_type,__VA_ARGS__); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
#define CCB_CREATE(object_type) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
INSERT_LOADER_MAP(object_type); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
Run Code Online (Sandbox Code Playgroud) 使用宏而不是静态内联方法有什么显着的好处吗?特别是,如何使用静态内联方法在调用链中进一步实现可变参数的传递,而这可以通过宏一步完成?
#define myprintf(fmt, args...) printf (fmt, args)
Run Code Online (Sandbox Code Playgroud)
这只是一个简单的示例,但我仍然很好奇是否有一种等效的方法可以使用静态内联而不使用 va_args 步骤来执行此操作。
编译器是否总是内联静态内联方法?它们的尺寸又如何呢?调用任意子方法怎么样?如果我使用多个宏,所有宏都会编译成单个表达式,因此编译器可能更容易优化。编译器是否总是足够聪明,可以将多个级别的静态内联调用转换为单个表达式?
如何定义一个C宏IFARGS(YES, NO, ...),以便IFARGS在没有其他参数的情况下进行NO调用,并IFARGS使用一个或多个参数进行调用YES?
我有一个使用GCC的答案(见下文),但如果可能的话,我更喜欢C99(或其不可能的证明).
我正在尝试使用宏生成函数声明
/* goal: generate int f(int a, float b) */
template<typename P>
struct ptype;
template<typename P>
struct ptype<void(P)> { typedef P type; };
#define NAMEe
#define COMMAe
#define COMMA ,
#define NAME(N) N PARAMS
#define PARAMS(P, ...) COMMA ## __VA_ARGS__ P NAME ## __VA_ARGS__
#define PARAM_ITER(P) P NAME
#define PROTO(R, N, P) \
ptype<void R>::type N (PARAM_ITER P (,e))
PROTO((int), f, (int)(a)(float)(b));
Run Code Online (Sandbox Code Playgroud)
它将使用具有空的宏参数来迭代地处理下一个(name)或(type)按NAME或PARAMS分别...。但海湾合作委员会抱怨
prototype.hpp:20:35: warning: ISO C99 requires rest arguments …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写dbgassert类似于标准的宏assert。除了做什么以外assert,我还想dbgassert打印任意数量的其他参数(包含调试信息)。
下面列出了我到目前为止所拥有的,这是从SO答案改编而来的。但是我在代码中存在可变参数模板或宏的问题。如果我至少使用一个附加参数(“确定”行),则dbgassert可以按预期工作。但是,如果我不给出其他参数,则编译将失败(问题行)。
我在可变参数模板编程方面有一些经验(例如如何打印元组),但是我以前从未使用过可变参数宏。
能否请您解释编写这种可变参数宏组合的正确方法是什么?
顺便说一句,有人可以解释 #EX在宏中魔术吗?它显示了表达式并在gcc4.8.1上为我工作。它得到普遍支持吗?
谢谢,
码:
//corrected reserved identifier issue and assumption issues per comments
#include <cassert>
#include <iostream>
using namespace std;
template <typename ...Args>
void realdbgassert(const char *msg, const char *file, int line, Args ... args) {
cout << "Assertion failed! \nFile " << file << ", Line " << line << endl
<< " Expression: " << msg << endl;
std::abort();
}
#define …Run Code Online (Sandbox Code Playgroud) #define UPUT_SET_CHECK_POINT1(appType, tag, argNum1, v1, ...) \
if(NUMARGS(##__VA_ARGS__) == 0) \
UPUT_SET_CHECK_POINTx(1, appType, tag, argNum1, v1, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, __FILE__, __LINE__, UPUT_SEQUENTIAL); \
else \
UPUT_SET_CHECK_POINTx(1, appType, tag, argNum1, v1, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, __FILE__, __LINE__ , __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
所以当VA_ARGS为空时,我得到一个编译时错误"期望在'之前的primary-expression'"'token'.任何修复编译错误的方法.
void UPUT_SET_CHECK_POINTx(int numArg, CtblAppType appType, int tag, UputArgPos argNum1, int v1, UputArgPos argNum2, int v2, UputArgPos argNum3, int v3, UputArgPos argNum4, int v4, UputArgPos argNum5, int v5, char* fileName, unsigned …Run Code Online (Sandbox Code Playgroud) 在你说它重复之前,我已经读过:如何将可变数量的参数从一个函数传递到另一个函数?
我有这样的功能:
void tlog_function(t_log* logger, const char* message_template, ...) {
pthread_mutex_lock(&loggerLock);
log_function(logger, message_template, ...); // What I want to do..
pthread_mutex_unlock(&loggerLock);
}
Run Code Online (Sandbox Code Playgroud)
而另一个这样的功能,不是我的,我在第三方库中使用它:
void log_function(t_log* logger, const char* message_template, ...);
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我想要做的只是在这个函数中添加一个互斥锁以使其具有线程安全性,我知道我可以使用va_list但在这种情况下我无法更改第二个函数的代码,因为它在库中我只有.h文件.
那么,有没有办法实现这一目标?
我想要一个macro声明int一个给定名称和可选的初始化表达式.
我尝试在Stack Overflow上使用这个答案,但没有成功.
这是我试过的:
#define macro(...) int FIRST(__VA_ARGS__)(REST(__VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)
这样使用时没有问题:
macro(foo);
Run Code Online (Sandbox Code Playgroud)
但是当给出初始化器时会出现错误:
macro(foo, 42);
Run Code Online (Sandbox Code Playgroud)
另一种 - 只是使用时会在没有参数的情况下__VA_ARGS__从-pedanticGCC 发出警告.
我怎样才能解决这个问题?
()当没有初始化表达式时,是否也可以避免括号 - 这意味着没有零初始化但是默认?
请注意,我的真实用例不仅适用int于任何类型,而且使用像boost这样的第三方也不是一种选择.