我正在尝试做某种宏"重载",以便MACRO(某些东西)的扩展方式与MACRO(其他东西)不同.
使用我从这里得到的片段(我不确定它是否100%便携)和Boost PP库中的一些功能,我能够使它工作:D
//THESE TWO COUNT THE NUMBER OF ARGUMENTS
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)
//THIS ONE RETURNS THE PARAMETER AT POSITION _i FROM A LIST OF __VA_ARGS__
#define VA_ARG(_i, ...) BOOST_PP_ARRAY_ELEM(_i, (VA_NARGS(__VA_ARGS__), (__VA_ARGS__)))
//AND THIS ONE IS THE 'OVERLOADED' MACRO ;)
#define TEST(...) BOOST_PP_IF(BOOST_PP_EQUAL(1, VA_NARGS(__VA_ARGS__)), function_A(VA_ARG(0, __VA_ARGS__)), \ //1 parameter
BOOST_PP_IF(BOOST_PP_EQUAL(2, VA_NARGS(__VA_ARGS__)), function_B(VA_ARG(0, __VA_ARGS__) + VA_ARG(1, __VA_ARGS__)), \ //2 parameters
BOOST_PP_IF(BOOST_PP_EQUAL(3, VA_NARGS(__VA_ARGS__)), function_C(VA_ARG(1, __VA_ARGS__) + …Run Code Online (Sandbox Code Playgroud) 我在C中的#define语句中有可选参数的问题,或者更具体地说是gcc 4.2:
bool func1(bool tmp) { return false; }
void func2(bool tmp, bool tmp2) {}
#define CALL(func, tmp, ...) func(tmp, ##__VA_ARGS__)
int main() {
// this compiles
CALL(func2, CALL(func1, false), false);
// this fails with: Implicit declaration of function 'CALL'
CALL(func2, false, CALL(func1, false));
}
Run Code Online (Sandbox Code Playgroud)
这显然是一个人为的例子,但确实显示了问题.有谁知道我怎么能得到正确的"解决"的可选参数?
附加信息:如果我删除##之前__VA_ARGS__,并执行以下操作:
bool func2(bool tmp, bool tmp2) { return false; }
#define CALL(func, tmp, ...) func(tmp, __VA_ARGS__)
int main() {
CALL(func2, false, CALL(func2, false, false));
}
Run Code Online (Sandbox Code Playgroud)
编译,但它不再适用零参数,因为它将解决 func(tmp, ) …
我正在使用包含一组预处理器库的库.其中一个是FOR_EACH样式宏,它迭代a __VA_ARGS__并为每个参数调用用户提供的宏.用户提供的宏称为:SOME_MACRO(current_arg)
但是,问题是它只适用于使用单个参数的用户提供的宏.我正在尝试做一些特殊的事情,它涉及struct结构中a 和每个字段的名称.问题是,这需要宏的两个参数.
由于我正在使用的库只接受一元宏,有没有办法将另一个参数"绑定"到我的宏?
截至目前,我必须在宏中硬编码结构的名称.所以,如果struct我正在与之合作Foo,我必须说:
#define MY_MACRO(FIELD) /* do something with &Foo::FIELD */
Run Code Online (Sandbox Code Playgroud)
有没有我可以"绑定"第二个STRUCT参数到宏,也许还有一些间接,所以当库调用我的宏时,它将能够扩展为:
#define MY_MACRO(FIELD) /* do something with &STRUCT::FIELD */
Run Code Online (Sandbox Code Playgroud) 我有一个可变函数:
LogWrite(FILE * fp, int level, const char * filename, const char * function, ...)
Run Code Online (Sandbox Code Playgroud)
它应该像这样调用:
LogWrite(fp, int Level, __FILE__, __FUNCTION__, "Message: %s", message)
Run Code Online (Sandbox Code Playgroud)
但是,我想编写一个可变参数宏,以便更容易调用:
1: #define LOGWRITE_L1(...) LogWrite(file, 1, __FILE__, __FUNCTION__, ...)
or
2: #define LOGWRITE_L1(file, ...) LogWrite(file, 1, __FILE__, __FUNCTION__, ...)
Run Code Online (Sandbox Code Playgroud)
这样开发人员可以使用以下方法调用它:
LOGWRITE_L1(myfile, "Hello!");
Run Code Online (Sandbox Code Playgroud)
代替
LogWrite(myfile, 1, __FILE__, __FUNCTION__, "Hello!")
Run Code Online (Sandbox Code Playgroud)
但是,这两种方法都给我一个编译器错误.
1: expected expression before '...'
2:'file' undeclared (first use in this function)
Run Code Online (Sandbox Code Playgroud)
这可能还是我在浪费时间?我以前从未使用过变量函数,所以不确定.我的功能工作......我使用完整的声明调用它,并写入我想要的文件.
使用gcc 4.6.3(带-ansi -pedantic),我有以下代码:
// Argument counting macro
#define NARGS(...) NARGS_(__VA_ARGS__, 5, 4, 3, 2, 1)
#define NARGS_(_1, _2, _3, _4, _5, _, ...) _
static inline void fi_init_(size_t nargs, fileinfo_t *finfo, ...) {
// Default fmt/type values
char* fmt = "CD";
int type = 1000;
if (nargs == 2) {
va_list ap;
va_start(ap, hdr);
fmt = va_arg(ap, char*);
type = va_arg(ap, int);
va_end(ap);
}
// Do some junk with it
}
#define fi_init(...) fi_init_(NARGS(__VA_ARGS__)-1, __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
当被称为:
fileinfo_t out; fi_init(&out);
Run Code Online (Sandbox Code Playgroud)
我收到警告: …
我有一个FOO(...)接收未知数量参数的宏.我想把所有这些参数都用于uint.有没有办法实现它?
我创建了一个用于makefile的宏:
TODO_MSG = $(warning TODO: $(1))
$(call TODO_MSG, This part of the msg displays fine, but this part does not)
Run Code Online (Sandbox Code Playgroud)
我可以通过以下方式解决这个问题:
BLAH := $(shell perl -e 'print join( " ", 2..200 )'
COMMA := ,
TODO_MSG = $(warning TODO:$(1)$(strip $(foreach x,${BLAH},$(if $(${x}),${COMMA}$(${x}))))
Run Code Online (Sandbox Code Playgroud)
...但我很好奇是否有任何东西可以为变量宏提供更明确的支持.
我需要能够得到以下内容:
#define MY_MACRO(PARAM1,PARAM2) \
MY_OTHER_MACRO(TYPENAME_OF(PARAM1),PARAMNAME_OF(PARAM1));\
MY_OTHER_MACRO(TYPENAME_OF(PARAM2),PARAMNAME_OF(PARAM2));\
Run Code Online (Sandbox Code Playgroud)
引起
MY_MACRO(int x,char *z)
Run Code Online (Sandbox Code Playgroud)
编译为
MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char*,z);
Run Code Online (Sandbox Code Playgroud)
如果它编译为:它不会是世界末日:
MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char,*z);
Run Code Online (Sandbox Code Playgroud)
或者甚至这也可以:(我可以编码MY_OTHER_MACRO来处理任何一个结果)
MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char,z);
Run Code Online (Sandbox Code Playgroud)
或者,如果有一些方法来计算由空格分隔的标记(并假设"*"是单独的标记,我也可以使用它 - 例如2对3)通常,标记用逗号分隔,至我知道.有没有办法使用另一个角色?
/* Debugging */
#ifdef DEBUG_THRU_UART0
# define DEBUG(...) printString (__VA_ARGS__)
#else
void dummyFunc(void);
# define DEBUG(...) dummyFunc()
#endif
Run Code Online (Sandbox Code Playgroud)
我已经在C编程的不同标头中看到了这种表示法,我基本上理解了它在传递参数,但是我不明白这种“三点表示法”是什么意思?
有人可以举例说明它还是提供有关VA Args的链接?
我运行cl/P test.cpp,文件和结果如下.
TEST.CPP
#define FiltedLog( ...) \
if (logDetail) \
MP_LOG(LOG_INFO, __VA_ARGS__);
#define MP_LOG(level,fmt,...) \
BOOAT::LOG("MP", level, fmt, ##__VA_ARGS__)
#define LOG(tag,level,fmt,...) \
Log::log(tag, level, "%s: " fmt, __PRETTY_FUNCTION__, ##__VA_ARGS__)
int main ()
{
FiltedLog ( "abc", 1, 2);
}
Run Code Online (Sandbox Code Playgroud)
Cl/P test.cpp:
#line 1 "test.cpp"
int main ()
{
if (logDetail) BOOAT::Log::log("MP", LOG_INFO, "%s: " "abc", 1, 2, __PRETTY_FUNCTION__ );;
}
Run Code Online (Sandbox Code Playgroud)
我想知道为什么__PRETTY_FUNCTION__把它作为结果中的最后一个参数.我假设结果应该是:
if (logDetail) BOOAT::Log::log("MP", LOG_INFO, "%s: " "abc", __PRETTY_FUNCTION__, 1, 2);;
Run Code Online (Sandbox Code Playgroud)
这是VS 2010的错误吗?
c++ variadic-functions visual-studio-2010 c-preprocessor variadic-macros
variadic-macros ×10
c ×6
macros ×3
c++ ×2
gcc ×2
c++11 ×1
c99 ×1
function ×1
gcc-warning ×1
gnu-make ×1