Reputation: 3223
I'd like to write a macro that in the following usage defines a global object foobar
of a class defined below it.
SOMEMACRO(foobar)
{
public:
int a;
};
In other words, I'd like the above to have the same effect as:
class SomeClassPossiblyWith_foobar_InItsName
{
public:
int a;
};
SomeClassPossiblyWith_foobar_InItsName foobar;
It's very important to giving exactly the "foobar" name to the object (or at least call in such a way a reference to the proper object). The name of class doesn't matter as long as it allow to use the macro several times.
It's rather hard, since class should be usually defined before it is used, but maybe there exist some tricky (possibly templates-involved) way of achieving it?
Upvotes: 3
Views: 230
Reputation: 2823
EDIT: Added more explanation to the codes.
A solution with templates would be as follows:
I have created a template for classes that should have an instance with global access when created. I think this is what you want. (I have named it as Singleton reffering to the design pattern with the name) .h:
// C++ header for template Singleton
template<typename T>
class Singleton : public T {
static Singleton<T>* instance;
Singleton();
public:
static Singleton<T>* getInstance();
};
getInstance() method will be from where you will get that instance. It can be an object instead of a pointer, but I like it better this way because it's more versatile with you want to do something more complex like changing the instance at runtime; also it allows to instantiate the object only when it is used, preventing no need memory alloc. .cpp:
// C++ source for template Singleton
template<typename T>
Singleton<T>* Singleton<T>::instance = NULL;
template<typename T>
Singleton<T>::Singleton()
: T()
{}
template<typename T>
Singleton<T>* Singleton<T>::getInstance()
{
if (instance == NULL)
{
instance = new Singleton<T>();
}
return instance;
}
You can implement any class you want normally and use Singleton template to ensure that you will always dealing with the same global instance of some class. You can also use a typedef to caliry type names, if you want. Your class definition:
// Definition of class foobar
class foobar_impl {
public:
int a;
};
typedef Singleton<foobar_impl> Foobar;
Then, you use the template to retreave the instance of foobar_impl:
int main(int argc, char** argv)
{
Foobar *pf = Foobar::getInstance();
return 0;
}
The problem of this solution, however, is that Singleton template will work only with classes that have an empty constructor. But so does your examples, so I think this is what you want.
Upvotes: 0
Reputation: 2823
You can do this way:
#define SING(classname, body) class SING_##classname \
body \
; SING_##classname classname;
Then, use it this way:
SING (foobar, {
public:
int a;
}
);
Upvotes: 1
Reputation: 3223
I a meantime I've found solution that make reference and initialize it with proper object, which somehow answer the question. I'm not sure it is standard complaint (it complies with gcc 4.6).
template<typename T>
T &delayed_make_object()
{
static T obj;
return obj;
}
#define DOIT(_name) \
class TypeFor ## _name; \
TypeFor ## _name & _name = delayed_make_object<TypeFor ## _name>(); \
class TypeFor ## _name
DOIT(foo)
{
public:
int abc;
};
DOIT(bar)
{
public:
int cba;
};
int main()
{
foo.abc=bar.cba; // works!
}
Upvotes: 1
Reputation: 409482
It very simple, using the preprocessor concatenation operator ##
.
Something like:
#define SOMEMACRO(name) \
SomeClassPossiblyWith_##name##_InItsName name; \
class SomeClassPossiblyWith_##name##_InItsName
Upvotes: 1