是否有可能在可变参数宏中的变量参数之前添加默认参数?例如,我有像宏的版本
#define MACRO(arg1, ...) func(arg1, ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
我想在变量参数之前在宏中添加另外2个默认参数,这样它就不会影响以前的版本.喜欢:
#define MACRO(arg1, arg2 = "", arg3 = "", ...) func(arg1, arg2, arg3, ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
任何帮助,将不胜感激.
我尝试获取发送到可变参数宏的第一个实际参数.这是我试过的,哪些在VS2010中不起作用:
#define FIRST_ARG(N, ...) N
#define MY_MACRO(...) decltype(FIRST_ARG(__VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)
当我查看预处理器输出时,我看到FIRST_ARG返回发送给MY_MACRO... 的整个参数列表
另一方面,当我尝试:
FIRST_ARG(1,2,3)
Run Code Online (Sandbox Code Playgroud)
它按预期扩展到1.
这似乎是臭名昭着的两级concat宏解决问题的逆转.我知道"宏参数在插入宏体之前已完全展开"但这似乎对我没有帮助,因为我不明白这意味着什么......和__VA_ARGS__
显然是__VA_ARGS__绑定,N只是稍后评估.我尝试了几种额外的宏观方法,但没有用.
我有一组用于实例化和初始化一组对象的方法.它们看起来几乎相同,除了传递给Init函数的参数数量:
ObjectType* CreateObjectType(Arg1 a1, Arg2 arg2, ... ArgN aN)
{
ObjectType* object = new ObjectType();
[...]
object->Init(this, a1, a2, ..., aN);
[...]
return object;
}
Run Code Online (Sandbox Code Playgroud)
请注意,除了要传递给Init函数之外,不能在任何地方使用参数.
我想找到一种方法来实现所有这些,而无需为每个对象类型复制代码.
我尝试使用可变参数宏,结果如下(无效):
#define CREATE_OBJECT_IMPL(ObjectType, ...) \
ObjectType* Create##ObjectType##(__VA_ARGS__) \
{ \
ObjectType* object = new ObjectType(); \
[...]
object->Init(this, ##__VA_ARGS__); \
[...]
return object; \
}
// This is the result I am trying to achieve :
CREATE_OBJECT_IMPL(MyFirstObject, bool, float)
CREATE_OBJECT_IMPL(MySecondObject, int)
CREATE_OBJECT_IMPL(MyThirdObject)
Run Code Online (Sandbox Code Playgroud)
现在,在这个实现中,我使用VA_ARGS两次,两次都不正确:
在第一种情况下,我想要一个包含我指定类型的参数列表(Arg1 a1,Arg2 a2 ......)
在第二种情况下,我想通过它们的名称(Init(a1,a2 ...))来调用这些参数. …
如何定义一个C宏IFARGS(YES, NO, ...),以便IFARGS在没有其他参数的情况下进行NO调用,并IFARGS使用一个或多个参数进行调用YES?
我有一个使用GCC的答案(见下文),但如果可能的话,我更喜欢C99(或其不可能的证明).
示例代码:
#define FOO(...) You passed: #__VA_ARGS__
FOO(1,2,3)
FOO()
Run Code Online (Sandbox Code Playgroud)
使用Visual C++(版本14 CTP)进行预处理,得到:
You passed: "1,2,3"
You passed:
Run Code Online (Sandbox Code Playgroud)
在最后一行,#__VA_ARGS__变成了虚无.我希望它变成"".
对于应该发生的事情,是否有明确的参考?我用Google搜索了很多但却找不到它.
任何建议的解决方案也很有用.
我正在尝试使用宏生成函数声明
/* 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) 我想写一个变量宏,它以某种方式知道传递的参数的名称.例如:
代码:
int x = 2;
float f = 4.6;
char c = 'A';
char* str = "Bla bla";
PRINT("%d %f %c %s", x, f, c, str); // calling the macro
Run Code Online (Sandbox Code Playgroud)
应产生输出
x=2 f=4.6 c=A str=Bla bla.
Run Code Online (Sandbox Code Playgroud)
希望有人知道答案.
我想知道是否有可能"嵌套"可变宏调用.我只关心GCC和Clang.我的宏定义如下:
/**
* @brief Invoke an instance method.
*/
#define $(obj, method, ...) \
({ \
typeof(obj) _obj = obj; \
_obj->interface->method(_obj, ## __VA_ARGS__); \
})
Run Code Online (Sandbox Code Playgroud)
我使用它在我的OO框架中方便地调用"实例方法"(https://github.com/jdolan/objectively):
$(array, addObject, obj);
Run Code Online (Sandbox Code Playgroud)
工作老板.不幸的是,我还没有找到一种允许嵌套这些调用的方法,这在某些情况下非常有用; 例如:
/**
* @see MutableSetInterface::addObjectsFromArray(MutableSet *, const Array *)
*/
static void addObjectsFromArray(MutableSet *self, const Array *array) {
if (array) {
for (size_t i = 0; i < array->count; i++) {
$(self, addObject, $(array, objectAtIndex, i));
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的嵌套可变参数宏调用无法编译,因为内部调用永远不会扩展.是否有可能解决这个问题,或者我已经将预处理器滥用到了极限?:)
如果我们定义一个宏
#define M(x, ...) { x, __VA_ARGS__ }
Run Code Online (Sandbox Code Playgroud)
然后使用它传递自身作为参数
M(M(1, 2), M(3, 4), M(5, 6))
Run Code Online (Sandbox Code Playgroud)
然后它扩展到预期的形式:
{ { 1, 2 }, { 3, 4 }, { 5, 6 } }
Run Code Online (Sandbox Code Playgroud)
但是,当我们使用##运算符时(为了防止在单参数调用的情况下在输出中出现悬空逗号,如GCC 手册中所述),即
#define M0(x, ...) { x, ## __VA_ARGS__ }
Run Code Online (Sandbox Code Playgroud)
那么在参数的扩展
M0(M0(1,2), M0(3,4), M0(5,6))
Run Code Online (Sandbox Code Playgroud)
似乎在第一个参数后停止,即我们得到:
{ { 1,2 }, M0(3,4), M0(5,6) }
Run Code Online (Sandbox Code Playgroud)
这种行为是一个错误,还是源于某些原则?
(我也用clang检查过它,它的行为方式与GCC相同)
我有 2 个可变宏,其中一个可以正常编译,另一个则不能:
#define ASSERT(x, ...) assert_log(x, __FILE__, __LINE__, __VA_ARGS__)
#define TRACE (x, ...) trace(x, __FILE__, __LINE__, __VA_ARGS__)
...
libs/defs.h:16:71: error: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro [-Werror]
16 | #define TRACE (x, ...) trace(x, __FILE__, __LINE__, __VA_ARGS__)
| ^
Run Code Online (Sandbox Code Playgroud)
他们宣布的签名:
void assert_log(int, const char*, int, const char* , ...);
void trace(int, const char*, int, const char* , ...);
Run Code Online (Sandbox Code Playgroud)
编译标志:
CFLAGS= \
-Wextra \
-Werror \
-Wall \
-Wfloat-equal \
-Wundef \
-Wshadow \ …Run Code Online (Sandbox Code Playgroud)