Question

How do I reverse the arguments to a variadic macro? For example, I'd like

#define REVERSE(...) ???

REVERSE(A,B,C) // expands to C,B,A

My goal is to separate the front and back arguments:

#define APPLY(FUN,...) FUN(__VA_ARGS__)

#define FRONT(FIRST,...) FIRST
#define REST(FIRST,...) __VA_ARGS__
#define MOST(...) APPLY(REVERSE,APPLY(REST,REVERSE(__VA_ARGS__)))
#define BACK(...) APPLY(FRONT,REVERSE_ARGUMENTS(__VA_ARGS__))

FRONT(A,B,C) // expands to A
REST(A,B,C) // expands to B,C
MOST(A,B,C) // expands to A,B
BACK(A,B,C) // expands to C
Was it helpful?

Solution

The Boost Preprocessor Library can reverse macro arguments. Unfortunately, it only works up to an implementation-defined maximum argument list length. As far as I can tell, it is not possible to write a macro that reverses an arbitrarily long list of arguments.

#include <boost/preprocessor.hpp>

#define REVERSE(...) BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_REVERSE(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)))

#define APPLY(FUN,...) FUN(__VA_ARGS__)

#define FRONT(FIRST,...) FIRST
#define BACK(...) APPLY(FRONT,REVERSE(__VA_ARGS__))
#define REST(FIRST,...) __VA_ARGS__
#define MOST(...) APPLY(REVERSE,APPLY(REST,REVERSE(__VA_ARGS__)))

OTHER TIPS

Here's an answer that doesn't use any external libraries.

There isn't a way to reverse an arbitrary length list in a macro because the compiler only makes one pass through the code, so loops and recursion aren't really possible. This code will work for lists up to length 10. It can be expanded for longer lists.

#define EXPAND(x) x

#define REVERSE_1(a) a
#define REVERSE_2(a,b) b,a
#define REVERSE_3(a,...) EXPAND(REVERSE_2(__VA_ARGS__)),a
#define REVERSE_4(a,...) EXPAND(REVERSE_3(__VA_ARGS__)),a
#define REVERSE_5(a,...) EXPAND(REVERSE_4(__VA_ARGS__)),a
#define REVERSE_6(a,...) EXPAND(REVERSE_5(__VA_ARGS__)),a
#define REVERSE_7(a,...) EXPAND(REVERSE_6(__VA_ARGS__)),a
#define REVERSE_8(a,...) EXPAND(REVERSE_7(__VA_ARGS__)),a
#define REVERSE_9(a,...) EXPAND(REVERSE_8(__VA_ARGS__)),a
#define REVERSE_10(a,...) EXPAND(REVERSE_9(__VA_ARGS__)),a
#define REVERSE1(N,...) EXPAND(REVERSE_ ## N(__VA_ARGS__))
#define REVERSE(N, ...) REVERSE1(N, __VA_ARGS__)

REVERSE takes the length of the va args list and the args list and returns its reverse.

To get the length of a list use this

#define _GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _9, _10, N, ...) N
#define NUM_ARGS(...) EXPAND(_GET_NTH_ARG(__VA_ARGS__,9,8,7,6,5,4,3,2,1,0))

I used this with msvc2015 which required the use of EXPAND. If you're using gcc/g++ it should work without EXPAND.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top