Reputation: 2328
I have a small question to the singleton pattern using C++. Let's say I have the following class:
namespace MyNameSpace
{
class Window_Singleton
{
private:
static Window_Singleton instance;
Window_Singleton();
/* Some more private stuff here */
public:
static Window_Singleton *GetInstance();
~Window_Singleton();
/* Some more public stuff here */
}
}
#define Window Window_Singleton.GetInstance()
I have this #define
so that I don't always have to write MyNameSpace::Window_Singleton.GetInstance().SomeMethod()
, I can now use the shorter MyNameSpace::Window.SomeMethod()
.
But the problem is: Now I cannot make a Window-class in another namespace because I will get problems with the define.
Is there a way to provide the #define
without "breaking" my namespace. Some sort of "namespace-local" define?
Upvotes: 0
Views: 1082
Reputation: 5566
I think there is not a way to use a macro, which ignores scope rules.
You might consider a typedef:
namespace MyNameSpace
{
class Window_Singleton
{
// ...
};
typedef Window_Singleton WS;
// ...
}
Your code can now use the typedef'd synonym / alias ...
// WS is alias/synonym for Window_Singleton
MyNameSpace::WS::SomeMethod(); // access to static method
MyNameSpace::WS ws; // declare instance
ws.SomeMethod2(); // access instance
Hint - I try to limit namespace names to 3 letters. Consider
namespace ETB; // for Exhauzt Tool Box
or
namespace EWS; // for Exhauzt Window Singleton
Upvotes: 0
Reputation: 27538
Is there a way to provide the #define without "breaking" my namespace. Some sort of "namespace-local" define?
Short answer: No.
Longer answer: Macros have no scope. That's what's sets them apart from other C++ features, for better or worse.
Complete answer:
ALL_CAPS
if you use any macro.A note on the last point: if you are concerned about MyNameSpace::Window_Singleton.GetInstance().SomeMethod()
being too long to read, then I can certainly sympathise with that. But that's still not a reason to infest your code with macros. You should instead use using
at local scope, a reference and possibly auto
to increase readability. Example:
void f()
{
using MyNameSpace::Window_Singleton;
auto& window = Window_Singleton.GetInstance();
window.SomeMethod();
}
Upvotes: 1
Reputation: 122830
I strongly suggest you not to use a #define
here. It actually does not spam the namespace but it can completele mess up any code that includes this define with hard to find errors. For example, once the symbol Window
is defined, a function
Foo(Bar* Window){ /*...*/}
is broken and in some cases you will have a hard time to spot such errors. Further it makes your code much harder to read. If I want to call a static function to get an instance and call a method, I expect the code to look like this:
Window_Singleton::GetInstance().SomeMethod();
while
Window.SomeMethod();
looks more like calling the method of some global instance. I mean you could use a global
Window_Singleton Window;
but as I understood, you dont want to use a global for the singleton. In summary: your code is easy to read if it reflects what you actually want to do. Calling a static method is least obfuscated when it looks like calling a static method. If you are lazy to type, use some editor with code completition, but dont make your code harder to read by using potentially dangerous defines.
PS: I have to mention that in my comments I was a bit confused. #defines
are completely unaware of namespaces. They are replacedin the code, before the compiler starts the actual work. Thats why it can be hard (if not impossible) to relate compiler errors caused by #defines
to the place where the symbol was defined.
Upvotes: 1
Reputation: 4275
As macros are expanded way before the compilation, the precompiler is not aware of things like classes, namespaces and so on. So no, if you define a macro Window
it will be used everywhere.
What you could do is define a function:
inline Window_Singleton& Window(){
return Window_Singleton.GetInstance();
}
and then write
Window().SomeMethod();
It's basically an additional pair of braces, but it will keep your code a lot clearer.
Upvotes: 2