Is there any way to stringify only the first argument of __VA_ARGS__
within a variadic macro? Maybe playing with disabling context could
do the trick?
a+, ld.
Answering to myself for archive ;-),
the answer is that it's not possible, AFAIK
One solution I had in mind was:
#define test_assert(...) \
COS_PP_IF(COS_PP_EQ(COS_PP_NARG(__VA_ARGS__),4)) \
(COS_CTR_ASS_(COS_PP_STR1(__VA_ARGS__##_),__VA_ARGS__), \
COS_CTR_ASS_(#__VA_ARGS__,__VA_ARGS__))
#define COS_CTR_ASS_(...) \
COS_PP_CAT_NARG(COS_CTR_ASS_,__VA_ARGS__)(__VA_ARGS__)
#define COS_CTR_ASS_2(CS,C) \
COS_CTR_ASS_3(CS,C,CS)
#define COS_CTR_ASS_3(CS,C,S) \
COS_CTR_ASS_6(CS,C,S,__FUNC__,__FILE__,__LINE__)
#define COS_CTR_ASS_5(CS,C,M,F,L) \
COS_CTR_ASS_6(CS,C,CS,M,F,L)
#define COS_CTR_ASS_6(CS,C,S,M,F,L) \
((void)((C) || (cos_exception_assert(S,M,F,L),0)))
The test_assert() macro should count the number of its arguments (line
1) and if it has 4 arguments, it adds COS_PP_STR1(__VA_ARGS__##_) in
front of the list (line 2) otherwise it adds the stringified
__VA_ARGS__ (line 3) which will be used only in the case of one
argument (i.e. CS in COS_CTR_ASS_2).
So in principle:
test_assert( cond );
test_assert( cond , func, file, line );
test_assert( cond , msg_str, func, file, line );
work fine. But the (more common) case:
test_assert( cond, msg_str ); // use COS_CTR_ASS_3
like in:
assert( 0 == 0, "bug in the compiler" );
doesn't work anymore. The reason is that I use the ## operator to
delay the expansion of __VA_ARGS__ in COS_PP_STR1(__VA_ARGS__##_) and
have the time to separate the arguments before the conversion of cond
to a string. But ## is evaluated before macros start to be scanned
(6.10.3.3 §3) and therefore before the lazy COS_PP_IF has a chance to
discard the invalid construction "..."##_ which appears in this later
case.
a+, ld.