17

Every once in a while, I stumble across some code that I'm maintaining that challenges the way I think about my code style. Today was one of those days...

I'm aware that about why you would want to use the scope operator to define global scope. In fact, here scope resolution operator without a scope is a great link tell you why.

However, I saw something that made me think today. All the classes in question were wrapped into a namespace for the project (good!), but I did see copious usage of the global scope operator. Namely, it was used for everything from C libraries (with the exception of uint8_t and the like... yes, the programmer used the .h version of this library since apparently the version of g++ they were running still threw warnings about the new C++ standard). Is this useful? I view this as just as a waste of characters (reminds me of using the this pointer... except in the case of the copy constructor and assignment operator where it helps in clarifying which object is which). Am I missing something? Sure, someone can come around and name something along the lines of usleep() or stderr (where I saw the most usage of "::"), but won't they know that doing so will probably break something horribly? At what point do you say "screw it" in terms of the scope operator and just tell yourself that someone who names a function a certain way within your namespace is asking for trouble?

So my question is... what is the "correct" (subjective I understand) way of using the global scope operator in this context? Should everything not included in std or your own namespaces have the global scope explicitly defined? I tend to err on the side of caution and use "std::" to avoid the using directive, but is anything gained from using the global scope operator here? I tend to think for clarity's sake it does lend to the fact that we aren't getting the variable or function in question from the current namespace, but I'm torn between including it and not given today's developments.

As always, thanks for the help and guidance as I look to make my code cleaner, more readable, and (of course) significantly more awesome.

Community
  • 1
  • 1
It'sPete
  • 5,083
  • 8
  • 39
  • 72
  • 5
    No narrowing down required. The question is a bit long, but pretty clear: "Should everything that is defined in global scope always be referred to using the `::` prefix?" – jogojapan Jun 25 '13 at 05:46
  • Namespaces are here just for you being able to name your function `usleep` or `stderr` *without* breaking stuff. – n. m. could be an AI Jun 25 '13 at 05:46
  • 2
    :: removes ambiguity, I would be hesitant to say it increases readability. Comes down to personal style and/or level of paranoia imo. – Jonathan Potter Jun 25 '13 at 05:48

4 Answers4

11

I use it quite infrequently; only when some ambiguity needs resolving for whatever reason. This is pretty subjective, though.

There may be some occasions (say, inside a template) where you're worried about ADL causing ambiguities only in certain cases:

template <typename T>
void foo(T t)
{
   ::bar(t);  // :: just in case there's a `bar` in `T`'s namespace
}
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3

There is almost no correct answer to this as it's almost totally style related, with the exception that if you think you may want to change from where you are going to import some declaration(s)/definition(s), in which case, when you use them, you don't specify any scope and import them using the using directive (to import a subset from the namespace) or the using namespace directive to import the entire set from the namespace.

Mostly the using directive is used as a convenience directive, but it is a powerful way to direct which declarations/definitions are used. My preference is to not specify the scope and import the declarations. Doing this allows for easy changes if ever they are needed while reducing visual noise. Also, specifying the scope would mean I'd be "locked in" from where I am getting the declarations (well, I'd have to do a global search and replace to change it).

If ever there is a conflict (you try an use a declared item with the same name that has been imported from more than one namespace) the compiler will let you know, so there's no real danger.

Adrian
  • 10,246
  • 4
  • 44
  • 110
1

Readable code is that has the least amount of noise. namespace prefixes normally provide nothing but noise. So baseline is to not have them at all.

Namespaces were introduced to C++ mainly to handle 3rd party stuff out of one's control. To allow libraries drop prefixing, while clients can use terse names by applying using.

Just because you can have the same name in many namespaces does not imply it is a good idea to too. If a project uses some environment, platform API, library set, whatever that puts name in global, those names are better be avoided for other purposes. As with or without prefixes they will bear mental overhead.

Use of :: is rare in well-shaped code, and frequent uses appear in wrapper classes for that same functionality.

Balog Pal
  • 16,195
  • 2
  • 23
  • 37
  • 1
    I agree that explicit namespace qualifications are visual clutter, I disagree with the rest, in particular the point about not reusing names. Some names are natural fits, not reusing them for your purpose would leave you with awkward naming. Furthermore, “explicit is better than implicit” and there are some cases (such as templates, see other answers) where explicit namespace qualification is a must. – Konrad Rudolph Jun 25 '13 at 09:09
  • such things can't be realistically stated in abstract -- on a code review people can agree whether some name is good or not so. I certainly forbid to re-purpose names in std:: whatever natural fit. Or those in WIN32 API outside wrappers. – Balog Pal Jun 25 '13 at 09:15
  • See, I believe that this is clearly excessive. `vector`, `list` and `copy` (just to name three) are names that crop up in certain applications all the time. Banning them is ludicrous. – Konrad Rudolph Jun 25 '13 at 09:20
1

Consider the following cases.

Public library.

You are writing an exportable library with public headers. And you absolutely have no clue in what environment your headers will be included. For example, someone may do:

namespace std = my_space::std;
#include "your_header"

And all your definitions will be corrupted, if you simply use: std::list<int>, etc. So, it's a good practice to prepend :: to everything global. This way you can be absolutely sure what you're using. Of course, you can do using (in C++11) or typedef - but it's a wrong way to go in headers.


Collaborative .cc/.cpp files.

Inside your own code that is not exposed to public in any way, but still editable not only by you - it's a good practice to announce, what you're going to use from outside of your namespace. Say, your project allows to use a number of vectors - not only an std::vector. Then, where it's appropriate, you put a using directive:

// some includes

using vector = ::std::vector<int>;  // C++11
typedef ::std::vector<int> vector;  // C++03

namespace my_namespace {
...
}  // namespace my_namespace

It may be put after all includes, or inside specific functions. It's not only gives control over the code, but also makes it readable and shortens expressions.

Another common case - is a mixing of global C functions and a C++ code. It's not a good idea to do any typedefs with function names. In this situation you should prepend C functions with the global scope resolution operator :: - to avoid compilation problems, when someone implements a function with a same signature in the same namespace.

Don't use :: for relative types and namespaces - or you'll lose the benefit of using namespaces at all.


Your own code.

Do what you want and how you want. There is only one good way - the way you fill comfortable with your own code. Really, don't bother about global scope resolution in this situation, if it's not requiered to resolve an ambiguity.

abyss.7
  • 13,882
  • 11
  • 56
  • 100