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