Variadic UNUSED function/macro
I took Dabo's (https://stackoverflow.com/a/23238813/5126486) awesome solution and improved a little bit so it's easier to extend to more than 5:
#define UNUSED0()
#define UNUSED1(a) (void)(a)
#define UNUSED2(a,b) (void)(a),UNUSED1(b)
#define UNUSED3(a,b,c) (void)(a),UNUSED2(b,c)
#define UNUSED4(a,b,c,d) (void)(a),UNUSED3(b,c,d)
#define UNUSED5(a,b,c,d,e) (void)(a),UNUSED4(b,c,d,e)
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5, N,...) N
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(100, ##__VA_ARGS__, 5, 4, 3, 2, 1, 0 )
#define ALL_UNUSED_IMPL_(nargs) UNUSED ## nargs
#define ALL_UNUSED_IMPL(nargs) ALL_UNUSED_IMPL_(nargs)
#define ALL_UNUSED(...) ALL_UNUSED_IMPL( VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__ )
What do you think about this:
#define UNUSED(...) [__VA_ARGS__](){};
Example:
void f(int a, char* b, long d)
{
UNUSED(a, b, d);
}
Should be expanded ad a lambdas definition:
[a,b,d](){}; //optimized by compiler (I hope!)
===== Tested with http://gcc.godbolt.org ===== I've tryed with this code:
#define UNUSED(...) [__VA_ARGS__](){};
int square(int num, float a) {
UNUSED(a);
return num * num;
}
The resulting output (compiled with -O0 -Wall) is:
square(int, float):
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movss %xmm0, -8(%rbp)
movl -4(%rbp), %eax
imull -4(%rbp), %eax
popq %rbp
ret
EDIT:
If you can use C++11 this could be a better solution :
template <typename ...Args>
void UNUSED(Args&& ...args)
{
(void)(sizeof...(args));
}
Here is a very simple approach that does not require any special tricks nor does it incur any runtime overhead.
Original Answer (C++ only)
#define UNUSED(...) (void)sizeof(__VA_ARGS__)
https://godbolt.org/z/Gz8MfvaTz
Updated Answer (C and C++)
I had forgotten to change the compiler from C++ to C, and thus the revised answer.
int main(int argc, char ** argv)
{
/* different types */
UNUSED(argc, argv);
/* many variables */
int w, x, y, z;
UNUSED(w, x, y, z);
/* single variable */
void * ptr;
UNUSED(ptr);
}
MSVC
/O2 /W4
No warnings from C and C++ compilers.
Clang
-O3 -Wall -Wextra
No warnings from C and C++ compilers.
GCC
-O3 -Wall -Wextra
No warnings from C++ compiler only.
For the C compiler, only the last parameter is ignored without warning. So at worst case, this version of UNUSED
is on par with the traditional #define UNUSED(x) ((void)x)
.
Based on these two posts Variadic macro to count number of arguments, and Overloading macros i made the following
#define UNUSED1(x) (void)(x)
#define UNUSED2(x,y) (void)(x),(void)(y)
#define UNUSED3(x,y,z) (void)(x),(void)(y),(void)(z)
#define UNUSED4(a,x,y,z) (void)(a),(void)(x),(void)(y),(void)(z)
#define UNUSED5(a,b,x,y,z) (void)(a),(void)(b),(void)(x),(void)(y),(void)(z)
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5, N,...) N
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)
#define ALL_UNUSED_IMPL_(nargs) UNUSED ## nargs
#define ALL_UNUSED_IMPL(nargs) ALL_UNUSED_IMPL_(nargs)
#define ALL_UNUSED(...) ALL_UNUSED_IMPL( VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__ )
what can be used as follows
int main()
{
int a,b,c;
long f,d;
ALL_UNUSED(a,b,c,f,d);
return 0;
}
eclipse macro expansion gives :
(void)(a),(void)(b),(void)(c),(void)(f),(void)(d)
compiled with gcc -Wall
with no warnings
EDIT:
#define UNUSED1(z) (void)(z)
#define UNUSED2(y,z) UNUSED1(y),UNUSED1(z)
#define UNUSED3(x,y,z) UNUSED1(x),UNUSED2(y,z)
#define UNUSED4(b,x,y,z) UNUSED2(b,x),UNUSED2(y,z)
#define UNUSED5(a,b,x,y,z) UNUSED2(a,b),UNUSED3(x,y,z)
EDIT2
As for inline
method you posted, a quick test
int a=0;
long f,d;
ALL_UNUSEDINLINE(a,f,&d);
gives ‘f’ is used uninitialized in this function [-Wuninitialized]
warning. So here at least one use case which breaks generality of this aproach