I have some code like this:
template<> const string &Wrapper<Foo>::s_Name = "Foo";
template<> const Binding Wrapper<Foo>::s_Bindings[] = {
Binding("m1", &caller<&Foo::f1>),
Binding("m2", &caller<&Foo::f2>),
Binding("m3", &caller<&Foo::f1>),
Binding("outer", &caller<&outer>),
};
template<> const int Wrapper<Foo>::s_BindingsLength =
(sizeof(ArraySizeHelper(s_Bindings)));
ArraySizeHelper here calculates array size in compile time. Non-member and member functions can be binded.
I wrote some macroses to save time when writing those bindings:
#define BIND_START(Class) \
namespace _Bind##Class##Namespace { \
typedef Class _BindClass; \
template<> const string &Wrapper<_BindClass>::s_Name = #Class; \
template<> const Binding Wrapper<_BindClass>::s_Bindings[] = {
#define BIND(FunctionName, Function) \
Binding(FunctionName, &caller<Function>),
#define BIND_END \
};\
template<> const int Wrapper<_BindClass>::s_BindingsLength = \
(sizeof(ArraySizeHelper(s_Bindings))); \
}
Now above piece of code can be written like this:
BIND_START(Foo)
BIND("m1", &Foo::f1)
BIND("m2", &Foo::f2)
BIND("m3", &Foo::f1)
BIND("outer", &outer)
BIND_END
A lot easier to type and read. Why do I need to put it in namespace? Because I can’t find another way to write those macroses in such a way that class name must be written only once (except member function pointers) and use it with several classes. And now I’m wondering, is it okay to do that? If not, is there any other way to implement functionality that I want?
Full code of this example on Pastebin
It’s appeared to be a bug in GCC 4.7.2 (not sure about other versions)
This code violates 9.4.2/2: “The definition for a static data member shall
appear in a namespace scope enclosing the member’s class definition.”
Here is bug report: GCC Bugzilla – Bug 56119
Your solution seems to be forbidden by the C++11 Standard. This is what 9.4.2/2 says:
“The declaration of a static data member in its class definition is not a definition and may be of an incomplete type other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition“
Now the namespace where you define the static member data (whose name is the result of evaluating the
_Bind##Class##Namespacepreprocessor expression) does not contain the namespace where the class is defined (which is, in your case, the global namespace). Thus, the static data member definition is illegal.I am not sure what compiler you are using, but if it compiles that, then it is a bug (and indeed that seems to be the case of GCC 4.7.2, for instance). Clang 3.2 correctly refuses to compile that and produces the correct output message:
source.cpp:106:1: error: cannot define or redeclare 's_Name' here because namespace '_BindFooNamespace' does not enclose namespace 'Wrapper<Foo>'BIND_START(Foo)
As for alternative solutions, I don’t think there are, as long as you need the class name in the expansion of
BIND_END(which is what you need for compile-time initialization ofs_BindingsLength). If the macro doesn’t get the class name as an argument, in fact, that name must be available as atypedef(this would be true if macros were allowed to expand into#definedirectives, but they are not). SinceBIND_ENDhas no hint on how to form the name of the class, it must look for a name which is always the same. And if the name must always be the same, it must be put into a separate namespace in order to avoid name clashes. But that is forbidden by the rule of the Standard mentioned above.In other words, I’m afraid you have to add one argument to the
BIND_ENDmacro. Which is not that bad, after all.