How to use __VA_ARGS__ in C or CPP [duplicate] - c++

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 question is that I need to use foo with variable number of arguments, is it possible to use __VA_ARGS__ ?
Like the line below:
#define FOO(...) __VA_ARGS__::do() ?
Thanks

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.

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.

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.

Related

Macro for calling a series of macro-generated functions with similar names (i.e. f_0, f_1, f_2, ...)

I got stuck with quite peculiar problem, and I at the moment have no idea how to solve it.
I am using the following block of macros to generate functions with similar names:
#define CONCAT_IMPLEMENTATION(arg1, arg2) arg1 ## arg2
#define CONCAT(arg1, arg2) CONCAT_IMPLEMENTATION(arg1, arg2)
#define UNIQUE_FUNCTION_NAME(index) CONCAT(f_, index)
#define GENERATE_FUNCTION() void UNIQUE_FUNCTION_NAME(__COUNTER__) ()
So code like this:
GENERATE_FUNCTION()
{
std::cout << "first function" << std::endl;
}
GENERATE_FUNCTION()
{
std::cout << "second function" << std::endl;
}
is replaced with:
void f_0 ()
{
std::cout << "first function" << std::endl;
}
void f_1 ()
{
std::cout << "second function" << std::endl;
}
Is there any way to implement a macro or a function that would call all the generated functions?
That is to say it would call functions from f_0 to f_N, where N is a current value of __COUNTER__ macro.
Something like that:
#define RUN_ALL_GENERATED_FUNCTIONS() // ??? //
int main()
{
RUN_ALL_GENERATED_FUNCTIONS();
return 0;
}
Looks rather impossible up to me. Could you give me any suggestions, please?
There is no need for macros here, just push function pointers into a vector then you can iterate through the vector calling each function in turn. One possible implementation would be:
#include <vector>
#include <functional>
#include <iostream>
struct Functions
{
static std::vector<std::function<void()>> functions;
template <typename T>
static T make_function(T f)
{
functions.push_back(f);
return f;
}
static void call()
{
for (auto& f : functions)
{
f();
}
}
};
std::vector<std::function<void()>> Functions::functions;
auto f_1 = Functions::make_function([]
{
std::cout << "first function" << std::endl;
});
auto f_2 = Functions::make_function([]
{
std::cout << "second function" << std::endl;
});
int main()
{
f_1();
f_2();
Functions::call();
}
If you really need to you could still wrap Functions::make_function into a macro.
There is no magic in preprocessor. To overload, you have to enumerate all possible cases anyway.
#define RUN_ALL_GENERATED_FUNCTIONS_1() UNIQUE_FUNCTION_NAME(0)();
#define RUN_ALL_GENERATED_FUNCTIONS_2() RUN_ALL_GENERATED_FUNCTIONS_1()UNIQUE_FUNCTION_NAME(1)();
#define RUN_ALL_GENERATED_FUNCTIONS_3() RUN_ALL_GENERATED_FUNCTIONS_2()UNIQUE_FUNCTION_NAME(2)();
#define RUN_ALL_GENERATED_FUNCTIONS_4() RUN_ALL_GENERATED_FUNCTIONS_3()UNIQUE_FUNCTION_NAME(3)();
#define RUN_ALL_GENERATED_FUNCTIONS() do{ CONCAT(RUN_ALL_GENERATED_FUNCTIONS_, __COUNTER__)() }while(0)
int main() {
RUN_ALL_GENERATED_FUNCTIONS();
// do{ f_0();f_1(); }while(0);
}
Note that __COUNTER__ is non-portable, you might as well use descriptive function names (and readability of the code is important and __func__ will expand to something meaningful) and put pointers to these functions into a custom linker section with __attribute__, then iterate over that section to execute all functions. It's typical to do that - within testing frameworks and in kernel, with .init and .fini etc. sections.

Best C++ macro for creating a new scope

I have a macro
#define SCOPE_GUARD(GUARD, NAME, ...) \
for(bool __once = true; __once; /* nothing */) \
for(GUARD NAME (__VA_ARGS__); __once; __once = false)
using something like this:
SCOPE_GUARD(std::unique_lock, lock, (some_mutex))
do_some();
or
SCOPE_GUARD(std::unique_ptr<char>, buff, (new char[BUFFER_SIZE])) {
*buff.get() = 0;
GetSomeDescription(buff.get(), BUFFER_SIZE);
Log(buff.get);
}
Are there similar(better) implementation of the macro, which is optimized by multiple compilers correctly.
P.S. Macro should be one, without finally macro like BOOST_SCOPE_EXIT_END (can redefine by if (...)).
EDIT
Simple scoupe in using codestyle is very huge.
{
std::unique_lock lock (some_mutex);
do_some();
}
but I want using some like this
SCOPE_GUARD(std::unique_lock, lock, (some_mutex)) do_some();
You can do an awful lot with C++ templates and lambda expressions. It might be worthwhile to explore using them. For example, instead of using the SCOPE_GUARD macro, you could do something like this:
template <typename G, typename F, typename... A>
inline auto scope_guard(G&&, F&& f, A&&... args)
-> decltype(std::forward<F>(f)(std::forward<A>(args)...))
{
return std::forward<F>(f)(std::forward<A>(args)...);
}
scope_guard(std::unique_lock<std::mutex>(m), do_something);
scope_guard(std::unique_lock<std::mutex>(m), [&]() {
do_something1();
do_something2();
do_something3();
});
If I were using straight macros, mine would probably look something like this:
#define UNWRAP(...) __VA_ARGS__
#define SCOPE_GUARD(X, Y) do { X; UNWRAP Y; } while (0)
SCOPE_GUARD(std::unique_lock<std::mutex> lock(m), (do_something()));
SCOPE_GUARD(std::unique_lock<std::mutex> lock(m), (
do_something1();
do_something2();
do_something3();
));
I think this is what you're looking for:
#define PROTECTED_BY(m) for(std::unique_lock<decltype(m)> _lock_(m) ; _lock_ ; _lock_.unlock())
complete use case:
#include <iostream>
#include <mutex>
#define PROTECTED_BY(m) for(std::unique_lock<decltype(m)> _lock_(m) ; _lock_ ; _lock_.unlock())
using namespace std;
int main()
{
mutex m;
PROTECTED_BY(m)
{
cout << "Hello World" << endl;
}
return 0;
}

How to extract __VA_ARGS__?

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 question is that I need to use foo with variable number of arguments, is it possible to use __VA_ARGS__ ?
Like the line below:
#define FOO(...) __VA_ARGS__::do() ?
Thanks
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.
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.
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.

C++ how to #define/rename a nested function?

namespace first {
namespace second {
class Third {
static void foo() {
std::cout << "foo\n";
}
};
}
}
void bar() {
std::cout << "bar\n";
}
#define first::second::Third::foo bar//this doesn't work
so, what's the correct way to map a nested function to another one?
Update:
a more similar situation is:
struct ReleaseVersion {
static void foo() {
std::cout << "release version\n";
}
};
struct DebugVersion {
static void foo() {
std::cout << "debug version\n";
}
};
#ifdef _DEBUG
#define ReleaseVersion::foo DebugVersion::foo
#else
#define DebugVersion::foo ReleaseVersion::foo
#endif
what I want to do is just like malloc and _malloc_dbg, when #define _CRTDBG_MAP_ALLOC, in debug mode, malloc will be mapped to _malloc_dbg, and in release mode, _malloc_dbg will be mapped to malloc
Update again
a more more similar situation is:
namespace first {
namespace second {
struct ReleaseVersion {
static void foo() {
std::cout << "release version\n";
}
};
struct DebugVersion {
static void foo(const char* file, long line) {
std::cout << "debug version\n";
}
};
}
}
#ifdef _DEBUG
#define ReleaseVersion::foo() DebugVersion::foo(__FILE__, __LINE__)
#else
#define DebugVersion::foo(file, line) ReleaseVersion::foo()
#endif
so, these 2 version of functions may have different parameters, I cannot just call one.
I know I can just do this
#ifdef _DEBUG
#define Foo() first::second::DebugVersion::foo(__FILE__, __LINE__)
#else
#define Foo() first::second::ReleaseVersion::foo()
but in this way, I must always use Foo(), even in the final release mode, it's still a macro.
I want to know if there are more flexible way to to do this.
One Solution
#ifdef _DEBUG
#define foo() foo(__FILE__, __LINE__)
#define ReleaseVersion DebugVersion
#else
#define foo(file, line) foo()
#define DebugVersion ReleaseVersion
#endif
int main() {
first::second::DebugVersion::foo(__FILE__, __LINE__);
first::second::ReleaseVersion::foo();
return 0;
}
it may be dangerous when there are another foo() or RealeaseVersion/DebugVersion in other namespaces,
but if you can make sure there won't, I think it can be an acceptable solution.
Your #define is the wrong way around:
#define bar first::second::Third::foo
means that bar will be replaced by first::second::Third::foo, which, I believe, is what you want.
This is the opposite of typedef, where things are the other way around.
I'm not exactly sure what you want, but this works:
namespace first {
namespace second {
class Third {
public: static void foo() {
std::cout << "foo\n";
}
};
}
}
#define bar first::second::Third::foo
int main()
{
bar();
}
The way malloc/free works is by a macro replacement:
#ifdef WANT_DEBUG_MALLOC
#define malloc(x) debug_malloc(x, __FILE__, __LINE__)
#define free(x) debug_free(x, __FILE__, __LINE__)
#endif
When the preprocessor sees struct foo *p = malloc(sizeof(struct foo) * 10); it will replace it with struct foo *p = debug_malloc(sizeof(struct foo) * 10, "myfile.c", 103);
However, as mentioned above, you can't really use namespaces when doing the macro replacement. You have to EITHER replace the namespace alone, or replace the function name alone. Of course, it's possible to have two macros, one to substitute the namespace, and one for substituting the function name. But it gets pretty messy pretty quickly, so best avoided, I'd say.
I would rather using inline functions
#ifdef _DEBUG
static inline void DoFoo() { DebugVersion::foo(); }
#else
static inline void DoFoo() { ReleaseVersion::foo(); }
#endif

Eliminating recursive template instantiation in C++

I want to define a macro that can be invoked in different places (at file scope) in order to create functions that do something. (In the example below the functions just print a message, but of course my real intent is to do some other useful stuff.) The challenge is that I want some "manager" function (in my example it will just be main()) to somehow succeed in getting them all invoked (in any order) without any of the code being dependent on the macro invocations (except for the macro invocations themselves, of course). What I mean is that once the file is written, another programmer would be able to just insert a few new macro invocations at various places or delete some of the existing invocations, and the code would still work without any further change. I realize this can be done using static objects but I want to explore a different approach. I'm going to use some template trickery and the fact that __LINE__ is monotone increasing.
#include <iostream>
using namespace std;
template<int i>
inline void f()
{
f<i-1>();
}
#define START_REGISTRATION \
template<> \
inline void f<__LINE__>() {} /* stop the recursion */ \
template<> void f<__LINE__>() /* force semicolon */
#define REGISTER(msg) \
template<> \
inline void f<__LINE__>() \
{ \
cout << #msg << endl; \
f<__LINE__ - 1>(); \
} \
template<> void f<__LINE__>() /* force semicolon */
// Unrelated code ...
START_REGISTRATION;
// Unrelated code ...
REGISTER(message 1);
// Unrelated code ...
REGISTER(message 2);
// Unrelated code ...
REGISTER(message 3);
// Unrelated code ...
// manager function (in this case main() )
int main()
{
f<__LINE__>();
}
This prints
message 3
message 2
message 1
as expected.
This solution has a few drawbacks.
Can't invoke REGISTER twice on the same line.
Will break if #line is played with.
Need to put the manager after all invocations of REGISTER.
Increased compile time due to the recursive instantiations.
Unless the "dummy" instantiations of f are all inlined away, the call-stack depth at runtime will be as great as the number of lines between START_REGISTRATION; and f<__LINE__>(); in the manager.
Code bloat: unless the "dummy" instantiations of f are all inlined away, the number of instantiations will similarly be be as great.
The excessive instantiation recursion depth is likely to hit the compiler's limit (500 by default on my system).
Issues 1-4 I don't really mind. Issue 5 can be eliminated by having each function return a pointer to the previous one, and having the manager use these pointers to call the functions iteratively rather than having them call each other. Issue 6 can be eliminated by creating a similar class template construct that is able to compute for each invocation of REGISTER what function was instantiated in the previous invocation and thus only instantiate the functions that actually do something. The excessive instantiation will then be shifted from the function template to the class template, but the class instantiations would only tax the compiler; they wouldn't trigger any code generation. So my real concern is Issue 7, and the question is: is there a way to restructure things so that the compiler does the instantiations iteratively rather than recursively. I am also open to different approaches altogether (apart from those involving static objects). One simple solution is to group all registrations together right before the manager (or add a STOP_REGISTRATION macro to end the block of registrations) but that would defeat a significant part of my purpose (registering stuff next to the code that defines it).
Edit: There have been some interesting suggestions, but I'm afraid I wasn't making myself clear in terms of what I hope to achieve. I'm really interested in two things: solving the problem as posed (i.e., no statics, single line per registration, no additional changes when adding/removing registrations, and, although I neglected to say so, only standard C++ --- hence, no boost). As I said in the comments below, my interest is more theoretical in nature: I'm hoping to learn some new techniques. Hence, I would really like to focus on restructuring things so the recursion is eliminated (or at least reduced) or finding a different approach that satisfies the constraints I laid out above.
Edit 2: MSalter's solution is a large step forward. At first I thought that every registration would incur the full cost of lines up to it, but then I realized that of course a function can be instantiated only once, so in terms of instantiations we pay the same price as in linear search, but the recursion depth becomes logarithmic. If I get around to it, I'll post a full solution eliminating Issues 5-7. It would still be nice, though, to see if it can be done in constant recursion depth, and best, with the number of instantiations linear in the number of invocations (a-la the boost solution).
Edit 3: Here's the full solution.
#define START_REGISTRATION \
template<int lo, int hi> \
struct LastReg { \
enum { \
LINE_NUM = LastReg<(lo + hi)/2 + 1, hi>::LINE_NUM ? \
static_cast<int>(LastReg<(lo + hi)/2 + 1, hi>::LINE_NUM) : \
static_cast<int>(LastReg<lo, (lo + hi)/2>::LINE_NUM) \
}; \
}; \
template<int l> \
struct LastReg<l, l> { \
enum { LINE_NUM = 0 }; \
}; \
template<int l> \
struct PrevReg { \
enum { LINE_NUM = LastReg<__LINE__ + 1, l - 1>::LINE_NUM }; \
}; \
template<int l> void Register() {} \
template<int l> void Register() /* force semicolon */
#define REGISTER(msg) \
template<> \
struct LastReg<__LINE__, __LINE__> { \
enum { LINE_NUM = __LINE__ }; \
}; \
template<> \
void Register<__LINE__>() \
{ \
cout << __LINE__ << ":" << #msg << endl; \
Register<PrevReg<__LINE__>::LINE_NUM>(); \
} \
template<> void Register<__LINE__>() /* force semicolon */
#define END_REGISTRATION \
void RegisterAll() \
{ \
Register<PrevReg<__LINE__>::LINE_NUM>(); \
} \
void RegisterAll() /* force semicolon */
START_REGISTRATION;
REGISTER(message 1);
REGISTER(message 2);
END_REGISTRATION;
int main()
{
RegisterAll();
}
The problem you face is that you're doing a linear search for f<i>, which causes an excessive number of instantiations.
The solution is to let f<i> call g<i,0>. This in turn calls g<i,i/2> and g<i/2,0>, which call g<i,i/2+i/4>, g<i/2+i/4,i/2>, g<i/2,i/4> and g<i/4, 0> ectetera. You'll of course specialize g<__LINE__, __LINE__> inside REGISTER().
Instantiating f<65536> will still cause 65536 template instantiations (you're effectively checking all previous 65536 lines), but the recursion depth is limited to log(65536), or 16 levels. That's doable.
Perhaps something like:
template<typename T>
struct register_struct {
virtual void operator()() = 0;
register_struct();
register_struct *pNext;
};
template<typename T>
struct registry {
static register_struct<T> *chain;
static void walk() {
register_struct<T> *p = chain;
while (p) {
(*p)();
p = p->pNext;
}
}
};
template<typename T>
register_struct<T> *registry<T>::chain = NULL;
template<typename T>
register_struct<T>::register_struct()
{
pNext = registry<T>::chain;
registry<T>::chain = this;
}
#define DECL_REGISTRY(name) \
struct tag_##name { } ; \
void name() { registry<tag_##name>::walk(); }
#define JOIN_EXPAND(x, y) JOIN_EXPAND_2(x, y)
#define JOIN_EXPAND_2(x, y) x ## y
// Invoke REGISTER_PRINT at file scope!
#define REGISTER_PRINT(name, text) \
namespace { \
static struct : public register_struct<tag_##name> { \
void operator()() { \
std::cout << text << std::endl; \
} \
} JOIN_EXPAND(rs_##name##_, __LINE__); \
}
DECL_REGISTRY(foo);
REGISTER_PRINT(foo, "hello")
REGISTER_PRINT(foo, "world")
int main() {
foo();
return 0;
}
This will fix the recursive instantiation issues, but you're still limited to one registration per line. However, since the registrations are at file scope, this should (hopefully!) be less of a problem.
Note that this is unsafe to use if you expect to invoke these prior to main() - you must allow static constructors to complete before using it.
I've once done something similar, which instantiates only a limited count of specializations. The goal was to aggregate all the specializations into an array of pointers and access them with a single method via the enum, but you easily can adapt it to your similar (as I suppose) needs.
#include <iostream>
using namespace std;
class I {
public:
virtual ~I() {};
virtual void P(int index) = 0;
enum Item {
Item0,
Item1,
Item2,
Item3,
Item4,
ItemNum
};
};
template <class T> class A: public I {
public:
A() {
Unroll<A<T>, ItemNum> tmp (m_F);
}
virtual ~A() {
}
void P(int index) { (this->*m_F[index])(); }
protected:
typedef void (A<T>::*F)();
F m_F[ItemNum];
template <int N> void p() { cout << "default!" << endl; }
template <class W, int C> struct Unroll
{
Unroll(typename W::F * dest)
{
dest[C-1] = & W::template p<C-1>;
Unroll<W, C-1> u(dest);
}
};
};
template <class T> template <class W> struct A<T>::Unroll<W, 0>
{ public: Unroll(typename W::F * dest) {} };
class B: public A<B>
{
public:
};
template <> template <> void A<B>::p<A<B>::Item1>() { cout << 1 << endl; }
template <> template <> void A<B>::p<A<B>::Item2>() { cout << 2 << endl; }
template <> template <> void A<B>::p<A<B>::Item4>() { cout << "it hacking works!" << endl; }
int main()
{
I *a = new B;
for (int i = 0; i < I::ItemNum; ++i) a->P(i);
return 0;
}
Here is a solution that limits recursion to the number of functions actually registered. Instead of using __LINE__ as the id, I used BOOST_PP_COUNTER, which is an incrementing counter available to the preprocessor.
The trick is that you can't increment the counter inside a macro since the increment is done through the inclusion of a header file. Consequently, I had to rely on file inclusion too, hence needing two lines instead of one to register a message (one line to define the message, and one line to actually register it).
Here is the code:
//register.hpp
#include <boost/preprocessor/slot/counter.hpp>
// general template function, not defined
template <unsigned int ID>
void f();
// base case, to stop recursion
template <>
void f<0>() {}
// macro to "hide" the name of the header to include (which should be in a
// "hidden" folder like "detail" in Boost
#define REGISTER() "actually_register_msg.hpp"
//actually_register_msg.hpp
#include <boost/preprocessor/stringize.hpp>
// increment the counter
#include BOOST_PP_UPDATE_COUNTER()
template<>
inline void f< BOOST_PP_COUNTER >()
{
std::cout << BOOST_PP_STRINGIZE( MSG_TO_REGISTER ) << std::endl;
f< BOOST_PP_COUNTER - 1 >(); // call previously registered function
}
// to avoid warning and registering multiple times the same message
#undef MSG_TO_REGISTER
// id of the last registered function
#define LAST_FUNCTION_ID BOOST_PP_COUNTER
// main.cpp
#define MSG_TO_REGISTER message 1
#include REGISTER()
#define MSG_TO_REGISTER message 2
#include REGISTER()
#define MSG_TO_REGISTER message 3
#include REGISTER()
int main()
{
f< LAST_FUNCTION_ID >();
}
Like your code, this prints
message 3
message 2
message 1
Of course, the registering call is a bit less pretty (one #define and one #include instead of a single macro call), but you avoid a lot of unecessary template instantiations.