13

If in C++ I have a class longUnderstandableName. For that class I have a header file containing its method declaration. In the source file for the class, I have to write longUnderstandableName::MethodA, longUnderstandableName::MethodB and so on, everywhere.

Can I somehow make use of namespaces or something else so I can just write MethodA and MethodB, in the class source file, and only there?

Stefano Borini
  • 138,652
  • 96
  • 297
  • 431
Eve
  • 131
  • 1
  • 1
  • 3
  • As of right now, the answer is no. **But**... There exists [a proposal to add **`namespace class`** to the language](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0223r0.html), which would achieve exactly what you, and I, want: enabling definition of already declared class members within a block that would automatically scope them to the class - and thereby avoid constant retyping of the class name scope, template arguments, etc. It's bizarre that it's taken until now and this is still only in proposal phase, but here we are. Sigh! I really hope this makes it into C++20 or whatever. – underscore_d Jul 14 '16 at 13:44
  • @underscore_d Sadly, that proposal doesn't include a `using class` equivalent, so it doesn't provide full flexibility still. – negamartin Oct 11 '16 at 06:22
  • @negamartin What else are you looking for? Please provide an example. The main point is that `namespace class` will resolve this repetition for the class's author, which is the perspective from which the OP asked this question. Users of the class, meanwhile, can do something like `using tiny_type = SomeNamespace::SomeOtherNamespace::AHugeClassName;`. What else do you want? – underscore_d Oct 11 '16 at 09:16
  • @underscore_d Imagine an enum inside a class, `GiganticallyLongClassName::CONSTANT1`, `GiganticallyLongClassName::CONSTANT2`and so on.. If the class was a namespace, I would be able to use inside a function `using GiganticallyLongNamespaceName;`, but since it's a class, I have to type `GiganticallyLongClassName::CONSTANT1` every time. With a `using class` directive something like `using class GiganticallyLongClassName;` would shorten it down to `CONSTANT1`, `CONSTANT2`, etc... I see no reason why this was not included in the proposal. – negamartin Oct 11 '16 at 10:04
  • @negamartin `I have to type GiganticallyLongClassName::CONSTANT1 every time.` Well, not _really_: as many others have pointed out (though I think in response to a different question than what was asked...) you could do `using g = GiganticallyLongClassName; g::CONSTANT1;` - but I see what you're getting at. I think there are proposals elsewhere for the kind of extensions of `using` you want, which I'm not sure is [ahem] within the scope of `namespace class`. – underscore_d Oct 11 '16 at 10:19

4 Answers4

14
typedef longUnderstandableName sn;

Then you can define the methods as

void sn::MethodA() {}
void sn::MethodB() {}

and use them as

sn::MethodA();
sn::MethodB();

This only works if longUnderstandableName is the name of a class. It works even if the class is deeply embedded in some other namespace.

If longUnderstandableName is the name of a namespace, then in the namespace (or source file) where you want to use the methods, you can write

using namespace longUnderstandableName;

and then call methods like

MethodA();
MethodB();

You should be careful not to use a using namespace foo; in header files, because then it pollutes every .cpp file that we #include the header file into, however using a using namespace foo; at the top of a .cpp file is definitely allowed and encouraged.

Luc Touraille
  • 79,925
  • 15
  • 92
  • 137
Ken Bloom
  • 57,498
  • 14
  • 111
  • 168
  • Does it really work? I mean typedef is a lifesaver to make abbrreviations, but declarations usually tend to need the original names. Have you used this approach? – Basilevs Nov 01 '10 at 08:50
  • @Basilevs: Declarations don't need the original names. A typedef doesn't "create a new type" that's different from the old one -- it just creates a new name that refers to the same old type. People use this approach all the time to translate something like `std::map::iterator` into something shorter. (And `std::map::iterator` already usually is a `typedef` for some class that's an implementation detail in the STL. – Ken Bloom Nov 01 '10 at 13:49
  • But that is not declaration of iterator. What you quoted is a usage of type iterator declared elsewhere. – Basilevs Nov 01 '10 at 14:06
  • @Baslievs: it's common to see someone `typedef std::map::iterator MapIt` so that they can refer to the `MapIt` type in loops and save some typing. It also used to be common in C to see someone `typedef Foo* FooPtr`, though I don't know why people thought this typedef was useful. – Ken Bloom Nov 01 '10 at 14:16
  • That is usage of class. Your example is about its member definition. – Basilevs Nov 01 '10 at 19:37
  • @Basilevs: the example in my second comment is an elaboration of the part that I glossed over in my first comment, and the seocnd comment is about creating a **short usable alias** for a type with a long name, which is what the OP's question is about. – Ken Bloom Nov 02 '10 at 01:06
  • 3
    @Basilevs was asking if the typedef could be used when **defining** member functions, not when **using** them, which was (I think) the original question. In other words, is the following code correct `typedef longUnderstandableName sn; void sn::MethodA() {}`? (Apparently, it is.) – Luc Touraille Apr 05 '13 at 07:31
  • Why I can't `using ClassName::MethodA;` in cpp of other class, and then call it by simply `MethodA()`? (provided `MethodA` is static). – user1234567 Sep 24 '15 at 12:58
  • http://ideone.com/acYwJ5 demonstrates that you can use this trick when defining members. – Ken Bloom Aug 11 '17 at 02:22
1

Inside the methods of the classes, you can use the name without qualification, anyway: just drop the longUnderstandableName:: prefix.

In functions inside the class source file that are not methods, I suggest to introduce file-scope static inline functions, like so:

inline type MethodA(type param){
    return longUnderstandableName::MethodA(param);
}

Then you can call MethodA unqualified; due to the inline nature, this likely won't cost any runtime overhead.

Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
  • Yes, but this forces you to define the method inside the header, which is inefficient because it forces recompilation of all clients whenever the class changes. – Billy ONeal Oct 31 '10 at 23:09
  • 1
    No, it doesn't force you to do that. In fact, you shouldn't define the method in the header, but at the top of the class source file - else the shortcut would be globally available, which the OP doesn't want to happen. – Martin v. Löwis Oct 31 '10 at 23:20
  • 1
    Works only for static members. – Basilevs Nov 01 '10 at 14:08
  • @Basilevs: Sure, but the OP apparently is talking about static members, anyway, since for instances, he wouldn't normally need to type the class name at all in order to call a method. – Martin v. Löwis Nov 01 '10 at 16:59
  • @Martinv.Löwis Pretty sure context indicates they were talking about _defining_ methods out of line, which always requires the verbose full names. – underscore_d Oct 11 '16 at 09:17
0

I'm not sure I'd recommend it, but you could use a macro like:

#define sn LongUnderstandableName

void sn::MethodA(parameters) { ... }
int sn::MethodB(parameters) { ... }

and so on. One of the bad points of macros is that they don't respect scope, but in this case, the scope you (apparently) want is the source file, which happens to correspond (pretty closely) with the scope of a macro.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    +1, it's a fast solution, but I would not recommend it either. It's a recipe for disaster. – Stefano Borini Oct 31 '10 at 22:58
  • 1
    Yes -- I'd be much more likely to define it as a macro in the editor, so I only have to type the short name, and it's automatically expanded to the real one -- but nobody else has to be aware of that. – Jerry Coffin Oct 31 '10 at 23:04
  • You could use a typedef instead. – Ken Bloom Oct 31 '10 at 23:13
  • 4
    -1 to make typedef answer better :) – Basilevs Nov 01 '10 at 08:48
  • While you *could* use `typedef` instead, and there are times/situations where `typedef` provides a real advantage, this does *not* seem to be one of them. For this situation, `typedef` is an equivalent answer, not a better one. – Jerry Coffin Nov 01 '10 at 15:09
  • Couldn't you "scope" the define by just using #undef at the end of all the member function definitions? – Taron Jan 04 '23 at 19:40
0

Well, yes, once you understand namespaces.

Instead of naming your class MyBonnieLiesOverTheOcean, instead set up the following:

namespace My { namespace Bonnie { namespace LiesOverThe {
   class Ocean { ... };
} } }

Now, when defining your methods, you put the same namespaces around the whole file, and you write:

Ocean::SomeMethod() ...

When using the class from outside all the namespaces, it's:

My::Bonnie::LiesOverThe::Ocean

If you need to reference a lot of things from some other namespace in some source file, you can use the 'use' directive to ditch the prefixes.

bmargulies
  • 97,814
  • 39
  • 186
  • 310