views:

106

answers:

4

Hi,

Simple question, how do I shorten a call/name without using defines.

For example, I have a singleton that I have to call that is within a namespace (I cannot use using namespace blabla because it is not allowed) like so:

MyFW::GameRoot::Instance()->DoSomething();

Now I can assign that to a variable, which works somewhat if I am using it multiple times within the same class/function, but using it in many classes/functions it becomes cumbersome. I decided to use #define for it:

#define MyFW::GameRoot::Instance() ROOT //defined in GameRoot.h

ROOT->DoSomething(); //Used where-ever GameRoot.h is included

Much better, and I really like it especially because now wherever I see ROOT (color coded through V-Assist) I know what it is immediately... unless I have a breakpoint there and I need Visual Studio to resolve ROOT to show up in the watch window (or even hover over it to quickly pull up the object in debug), which it cannot do.

Is there any other option? What do you guys do to shorten names? Simply use local/member pointers to store the instance?

Thanks!

+5  A: 

Use local references:

MyFW::GameRoot& ROOT = MyFW::GameRoot::Instance();

Do not use defines.

akira
This unnecessarily adds a new variable to solve a syntactic problem.
cape1232
the assembler code i am looking at tells me otherwise.
akira
In case you're wondering: for some reason SO decided to lock my vote in immediately after a misclick, thus a minor edit.
Georg Fritzsche
i am far away from wondering :)
akira
@cape1232, reference is not a variable actually. It's just an alias for actual object. You cannot assign new value to the reference and using it doesn't have any cost in the result machine code.
Kirill V. Lyadvinsky
Isn't MyFW::GameRoot a class. Can you have a reference to a class to later call it's static members?
Sergej Andrejev
Looks like `MyFW::GameRoot::Instance()` returns a pointer to `MyFW::GameRoot`. You could dereference the pointer and then initialize the reference.
Kirill V. Lyadvinsky
@Sergej: That would be a `typedef`.
Georg Fritzsche
which is also just an alias and implies no runtime costs...
akira
+1  A: 

The good way to do this (but never in a header) is

using MyFW::GameRoot;
GameRoot::Instance()->DoSomething;

This is a using declaration and is different from a using directive, which is what you mentioned above.

rlbond
This syntax assumes GameRoot is a class.
rlbond
Forget i said anything, that must have been some minor brain malfunction :)
Georg Fritzsche
+5  A: 

You can't use using namespace ..., but can you use

namespace root=MyFW::GameRoot;

Then you can type

root::Instance()->DoSomething();

Defining a namespace like that is better than a #define. (I.e it can't get munged up somewhere else by mistake. The compiler knows what you are trying to do.)

cape1232
+1, this is one of those less used C++ features, also mentioned here: http://stackoverflow.com/questions/75538/hidden-features-of-c/78484#78484
Naveen
While we're in picking mode - how much better is that now: `root::Instance()->f(); root::Instance()::g(); root::Instance()::h();`.
Georg Fritzsche
namespace MyFW { class GameRoot { ... } }; at least my compiler tells me "foo.cc:36: error: `GameRoot' is not a namespace-name"
akira
@Georg I agree it is minimally shorter in this case (though you could use `namespace r=...`. I get lots of use out of this technique because I use code that is often nested in 3 levels of namespace with long names.
cape1232
I realize I am replying here after quite some time, but I just tried this on another 'problem' area that I ran into and remembered your solution. `namespace newAlias= SomeNameSpace::ClassName;` does not work because a namespace alias can only be given to an existing namespace and not a symbol. So in this question's case, I can only give an alias to `MyFW` which is already short enough to not really require an alias. If the above is wrong, I would grateful for corrections/clarification. Thanks.
Samaursa
+2  A: 

If you want to ease access across multiple functions, just use a helper function:

namespace {
    MyFW::GameRoot* root() { return MyFW::GameRoot::Instance(); }
}

// ...
root()->DoSomething();

Two characters more, but it with comes type-safety included.

Georg Fritzsche
This unnecessarily adds function call cost at runtime.
cape1232
@cape: No it won't unless you are using an antique compiler. The definition is visible and any compiler worth its grain will produce the same results. Check your facts first before downvoting.
Georg Fritzsche
Touche on that. Separate objection is that it hides the use of Instance(), though. When you're debugging, you say, "Hey, what's root again, where'd it come from?"
cape1232
@cape: Thats what the source code is for - use *"jump to definition"* or however your IDE calls it. Whenever you make something more concise you hide information to some degree, so ... I could object to your answer on the same grounds - where is that namespace coming from?
Georg Fritzsche
exactly. compilers throw such helpers away. the same for references, see my answer.
akira
I like the other answers below as well (especially cape1232's suggestion which is to use namespace root = MyFW::GameRoot, I did not know this particular C++ feature) but in this particular case, this answer works for me the best. I actually want to hide the call to Instance() as well. I am using Ogre3D and with Ogre, the calls are even longer, i.e. GetSinglestonPtr(), which is a pain to write everytime even with intellisense and wastes space. I can easily hover over root to see what it is if I want to.
Samaursa
@Georg First, I sense some annoyance at the fine distinctions I drew. I'm not criticizing, and I don't want to seem unfriendly. All the solutions here are good enough. But I still like `root=...` because you're hiding a namespace with a namespace. They're both the same thing.
cape1232
Correct me if I'm wrong... You can actually require a compile to insert function code inline (the thing Georg Fritsche talks about) into a place where it is called from by ussing inline keyword (http://www.cppreference.com/wiki/keywords/inline). This is for compiles who don't support this
Sergej Andrejev
@sergej: Compilers are free to ignore `inline` and are also free to inline functions not marked as such. Todays compilers will inline aggressively either way, especially in simple cases like this.
Georg Fritzsche
@cap: Your comments read as pointing out mistakes to me. Sure, you yourself can post and use whatever approach you like, but don't assume its better without presenting correct facts.
Georg Fritzsche