0

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?

5
  • 1
    the way not to make the #define "break" your namespace is not to use a #define here. You mainly obfuscate your code with it, just dont do it and you wont have the problem Commented Feb 13, 2016 at 10:48
  • But then I don't have the shorter way to access my singleton Commented Feb 13, 2016 at 10:49
  • if you are lazy with typing you should use an IDE rather than making your code harder to read and spamming the namespace Commented Feb 13, 2016 at 10:50
  • but isn't Window.SomeMethod() easier to read than Window.GetInstance().SomeMethod() ? Commented Feb 13, 2016 at 10:52
  • If your heart is set on using macros, a good convention is to write them in all caps with a specific prefix. In your case, something like MY_NS_WINDOW would probably stop it from clashing with other tokens. Commented Feb 13, 2016 at 11:11

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

1

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:

  • Don't use macros if you can avoid it.
  • Use ALL_CAPS if you use any macro.
  • Don't use the Singleton pattern at all.
  • Easy writing is not a relevant factor in code quality.

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(); } 

Comments

0

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 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.