25

In C++, should we be prepending stuff in the global namespace with ::?

For example, when using WinAPI, which is in C, should I do ::HANDLE instead of HANDLE, and ::LoadLibrary instead of LoadLibrary? What does C++ say about this? Is it generally a good idea, factoring in issues like readability and maintainability?

  • 4
    Slightly more generally: Is it good practice to overqualify names? E.g. if I'm inside `namespace foo { ... }`, should I feel safe in assuming that `get()` will call my `foo::get()`, or should I write `foo::get()` or even `::foo::get()` to be on the safe side? What are the costs and benefits of doing so? – j_random_hacker Oct 05 '11 at 14:35
  • I'm currently handling project with multiple modules and sourcefiles. I realized lately that I should use `::` for win32 APIs when I call them inside a module so calling member functions won't look like calling an api from global scope. I don't prefer typing `this->PlayMemberFunc()` over `PlayMemberFunc()` unless there's a need to clear confusion in the current block where that member function is called. – acegs Jul 31 '19 at 07:46

7 Answers7

12

Names in C++ can be qualified and unqualified. There are different rules for qualified and unqualified name lookup. ::HANDLE is a qualified name, whereas HANDLE is an unqualified name. Consider the following example:

#include <windows.h>

int main()
{
    int HANDLE;
    HANDLE x; //ERROR HANDLE IS NOT A TYPE
    ::HANDLE y; //OK, qualified name lookup finds the global HANDLE
}

I think that the desicion of choosing HANDLE vs. ::HANDLE is a matter of coding style. Of course, as my example suggests, there might be situations where qualifying is mandatory. So, you might as well use :: just in case, unless the syntax is somewhat disgusting for you.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
9

As namespaces don't exists in C, don't use ::HANDLE to access HANDLE type.

Using the prepending :: for global namespace is a good idea for readability, you know the type you want to access is from global namespace.

Moreover, if you are in a nested namespace and declare your own HANDLE type (for example), then the compiler will use this one instead of windows.h one!

Thus, always prefer using :: before names when working in nested namespace.

Jaffa
  • 12,442
  • 4
  • 49
  • 101
5

The main point of interest is what the differences are from the point of view of the compiler, as it has already been said, if you include the :: then you are using qualified lookup, rather than unqualified lookup.

The advantage of using qualified lookup is that it will be able to pinpoint a particular symbol always. The disadvantage is that it will always pinpoint that particular symbol --i.e. it will disable Argument Dependent Lookup. ADL is a big and useful part of the language, and by qualifying you effectively disable it, and that is bad.

Consider that you had a function f in the global namespace, and that you added a type T inside namespace N. Not consider that you wanted to add an overload of f that would take a T as argument. Following the interface principle, you can add f to the N namespace, as f is actually an operation performed on T, and it so belongs with the type. In this case, if you had code that called (consider generic code) ::f(obj) on an object of unknown type U the compiler will not be able to pick up ::N::f(obj) as a potential overload as the code is explicitly asking for an overload in the global namespace.

Using unqualified lookup gives you the freedom of defining the functions where they belong, together with the types that are used as arguments. While it is not exactly the same, consider the use of swap, if you qualify std::swap then it will not pick up your hand rolled void swap( T&, T& ) inside your N namespace...

I would only fully qualify identifiers when the compiler would otherwise not pick up the element I want.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
4

It's largely a matter of style; there are no performance or efficiency concerns to speak of. It can be a good practice on large projects and projects intended to be compiled on many different platforms, as under these circumstances collisions between global names and names in a namespace are more likely to occur.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
4

Normally, you do not have to prepend :: for the global namespace. (Only in some really rare circumstances). IMHO it harms readability, but, on the other hand it probably won't break your code

Constantinius
  • 34,183
  • 8
  • 77
  • 85
2

I put all of my code into a namespace, and I tend to prefer the C++ headers over the C headers, so the only symbols left in the global namespace tend to be from the Windows API. I avoid pulling symbols from other namespaces into the current namespace (e.g., I never have using namespace std;), preferring instead to qualify things explicitly. This is in line with Google's C++ style guide.

I've therefore gotten into the habit of qualifying WinAPI function calls with :: for a few reasons:

  1. Consistency. For everything outside the current namespace, I refer to it explicitly (e.g., std::string), so why not refer to the Windows APIs explicitly (e.g., ::LoadLibraryW)? The Windows APIs namespace is the global namespace.

  2. A lot of the WinAPI functions are named generically (e.g., DeleteObject). Unless you're very familiar with the code you're reading, you may not know whether DeleteObject is a call to something in the current namespace or to the Windows API. Thus, I find the :: clarifies.

  3. A lot of Windows frameworks have methods with the same names as the raw calls. For example, ATL::CWindow has a GetClientRect method with a slightly different signature than WinAPI's GetClientRect. In this framework, it's common for your class to be derived from ATL::CWindow, so, in your class's implementation, it's normal to say GetClientRect to invoke the inherited ATL method and ::GetClientRect if you need to call the WinAPI function. It's not strictly necessary, since the compiler will find the right one based on the signature. Nevertheless, I find that the distinction clarifies for the reader.

(I know the question wasn't really about WinAPI, but the example was in terms of WinAPI.)

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
  • Interesting to read that somebody else follows the exact same strategy as I do; a lot of Windows API has fairly generic names, so I made a habit of always using the Windows API with fully qualified names. – Frerich Raabe Sep 14 '16 at 08:00
1

No, if you do not have a LoadLibrary method in your class you do not need to use the global scope. In fact, you should not use global scope because if you later on add a LoadLibrary to your class your intentions is probably to override the global function...

ragnarius
  • 5,642
  • 10
  • 47
  • 68