I hava a macro to call static function for each args.
For example:
#define FOO(X) X::do();
#define FOO_1(X,Y) X::do(); Y::do();
My
You cannot do this directly, __VA_ARGS__
is always treated as a single unit consisting of all the parameters separated by a comma. The preprocessor provides no built-in way to find the number of parameters, to separate them or to loop over them.
This answer to a similar question shows the basic solution using the preprocessor: Find out how many items there are in your argument list and pass it on to a macro that does take this exact amount of parameters.
I’d recommend not to do this but instead use Andy Prowls C++11 solution or even restructure your code so you don’t need this at all.
Macro expansion does not work like argument pack expansion with variadic templates. What you have will expand to:
X,Y::do();
And not to
X::do(); Y::do();
As you hoped. But in C++11 you could use variadic templates. For instance, you could do what you want this way:
#include <iostream>
struct X { static void foo() { std::cout << "X::foo()" << std::endl; }; };
struct Y { static void foo() { std::cout << "Y::foo()" << std::endl; }; };
struct Z { static void foo() { std::cout << "Z::foo()" << std::endl; }; };
int main()
{
do_foo<X, Y, Z>();
}
All you need is this (relatively simple) machinery:
namespace detail
{
template<typename... Ts>
struct do_foo;
template<typename T, typename... Ts>
struct do_foo<T, Ts...>
{
static void call()
{
T::foo();
do_foo<Ts...>::call();
}
};
template<typename T>
struct do_foo<T>
{
static void call()
{
T::foo();
}
};
}
template<typename... Ts>
void do_foo()
{
detail::do_foo<Ts...>::call();
}
Here is a live example.
Actually you can partially workaround this.
You can directly and freely extract every member of neither __VA_ARGS__
nor variadic templates of C++11. But you can have the very first element. For example let's say we have a macro named OUT(...)
and we want to produce std::cout << A << B << C ... where A, B, C are the variadic arguments of macro. Try this:
#include <iostream>
#define SEPERATOR <<
#define GET_1_OF(element1, ...) element1
#define GET_2_OF(element1, ...) element1 SEPERATOR GET_1_OF(__VA_ARGS__)
#define GET_3_OF(element1, ...) element1 SEPERATOR GET_2_OF(__VA_ARGS__)
#define BAR(...) GET_3_OF(__VA_ARGS__)
int main()
{
std::cout << BAR(1,2,3,4,5);
return 0;
}
This is of course not the solution you are after. But you can augment the number of GET_N_OF to do what you want. Note that SEPERATOR
is <<
so that we MACRO can write 1 << 2 << 3
and so on.
Now, we have a problem in this code. Please change BAR(1,2,3,4,5)
with BAR(1)
You will see that it is giving an error. This is because it was expecting 3 arguments, although it is not problem to have more arguments (because it is variadic) we are having extra SEPERATOR
. So in order to solve this problem instead of using BAR(...)
use GET_N_OF(...)
(since you know the number of arguments):
#include <iostream>
#define SEPERATOR <<
#define GET_1_OF(element1, ...) element1
#define GET_2_OF(element1, ...) element1 SEPERATOR GET_1_OF(__VA_ARGS__)
#define GET_3_OF(element1, ...) element1 SEPERATOR GET_2_OF(__VA_ARGS__)
#define GET_4_OF(element1, ...) element1 SEPERATOR GET_3_OF(__VA_ARGS__)
#define GET_5_OF(element1, ...) element1 SEPERATOR GET_4_OF(__VA_ARGS__)
int main()
{
std::cout << GET_5_OF(1,2,3,4,5);
std::cout << GET_1_OF(1);
return 0;
}
Please note that if you do not know what you are doing do not use MACROs at all! My response was just to share fun MACRO code that may be beneficial for you. I always discourage the usage of MACROs until they are remarkably necessary.