我有一个宏来为每个参数调用静态函数。
例如:
#define FOO(X) X::do();
#define FOO_1(X,Y) X::do(); Y::do();
我的问题是我需要使用 foo 和可变数量的参数,是否可以使用__VA_ARGS__
?
像下面的行:
#define FOO(...) __VA_ARGS__::do() ?
谢谢
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.
您不能直接执行此操作,__VA_ARGS__
始终将其视为由逗号分隔的所有参数组成的单个单元。预处理器没有提供内置方法来查找参数的数量、将它们分开或循环它们。
This answer to a similar question显示了使用预处理器的基本解决方案:找出参数列表中有多少项,并将其传递给一个宏,该宏确实采用了这个确切数量的参数。
我建议不要这样做,而是使用Andy Prowls C++11 解决方案,甚至重构你的代码,这样你就根本不需要它了。
实际上,您可以部分解决此问题。您可以直接、自由地提取C++11 的既不或可变参数模板的
每个成员。__VA_ARGS__
但是你可以拥有第一个元素。例如,假设我们有一个名为的宏OUT(...)
,我们想要生成 std::cout << A << B << C ... 其中 A、B、C 是宏的可变参数。尝试这个:
#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;
}
这当然不是您想要的解决方案。但是你可以增加 GET_N_OF 的数量来做你想做的事。请注意,这SEPERATOR
是<<
为了让我们可以编写 MACRO 1 << 2 << 3
等等。
现在,我们在这段代码中遇到了问题。请更改BAR(1,2,3,4,5)
为BAR(1)
你会看到它给出了一个错误。这是因为它期待 3 个参数,尽管有更多参数(因为它是可变参数)没有问题,但我们有额外的 SEPERATOR
. 所以为了解决这个问题而不是使用BAR(...)
use GET_N_OF(...)
(因为你知道参数的数量):
#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;
}
请注意,如果您不知道自己在做什么,则根本不要使用 MACRO!我的回应只是分享有趣的宏代码,可能对您有益。我总是不鼓励使用 MACRO,直到它们非常必要。