What is the meaning of prepended double colon "::"?
This ensures that resolution occurs from the global namespace, instead of starting at the namespace you're currently in. For instance, if you had two different classes called Configuration
as such:
class Configuration; // class 1, in global namespace
namespace MyApp
{
class Configuration; // class 2, different from class 1
function blah()
{
// resolves to MyApp::Configuration, class 2
Configuration::doStuff(...)
// resolves to top-level Configuration, class 1
::Configuration::doStuff(...)
}
}
Basically, it allows you to traverse up to the global namespace since your name might get clobbered by a new definition inside another namespace, in this case MyApp
.
The ::
operator is called the scope-resolution operator and does just that, it resolves scope. So, by prefixing a type-name with this, it tells your compiler to look in the global namespace for the type.
Example:
int count = 0;
int main(void) {
int count = 0;
::count = 1; // set global count to 1
count = 2; // set local count to 2
return 0;
}
Lots of reasonable answers already. I'll chip in with an analogy that may help some readers. ::
works a lot like the filesystem directory separator '/
', when searching your path for a program you'd like to run. Consider:
/path/to/executable
This is very explicit - only an executable at that exact location in the filesystem tree can match this specification, irrespective of the PATH in effect. Similarly...
::std::cout
...is equally explicit in the C++ namespace "tree".
Contrasting with such absolute paths, you can configure good UNIX shells (e.g. zsh) to resolve relative paths under your current directory or any element in your PATH
environment variable, so if PATH=/usr/bin:/usr/local/bin
, and you were "in" /tmp
, then...
X11/xterm
...would happily run /tmp/X11/xterm
if found, else /usr/bin/X11/xterm
, else /usr/local/bin/X11/xterm
. Similarly, say you were in a namespace called X
, and had a "using namespace Y
" in effect, then...
std::cout
...could be found in any of ::X::std::cout
, ::std::cout
, ::Y::std::cout
, and possibly other places due to argument-dependent lookup (ADL, aka Koenig lookup). So, only ::std::cout
is really explicit about exactly which object you mean, but luckily nobody in their right mind would ever create their own class/struct or namespace called "std
", nor anything called "cout
", so in practice using only std::cout
is fine.
Noteworthy differences:
1) shells tend to use the first match using the ordering in PATH
, whereas C++ gives a compiler error when you've been ambiguous.
2) In C++, names without any leading scope can be matched in the current namespace, while most UNIX shells only do that if you put .
in the PATH
.
3) C++ always searches the global namespace (like having /
implicitly your PATH
).
General discussion on namespaces and explicitness of symbols
Using absolute ::abc::def::...
"paths" can sometimes be useful to isolate you from any other namespaces you're using, part of but don't really have control over the content of, or even other libraries that your library's client code also uses. On the other hand, it also couples you more tightly to the existing "absolute" location of the symbol, and you miss the advantages of implicit matching in namespaces: less coupling, easier mobility of code between namespaces, and more concise, readable source code.
As with many things, it's a balancing act. The C++ Standard puts lots of identifiers under std::
that are less "unique" than cout
, that programmers might use for something completely different in their code (e.g. merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). Two unrelated non-Standard libraries have a far higher chance of using the same identifiers as the authors are generally un- or less-aware of each other. And libraries - including the C++ Standard library - change their symbols over time. All this potentially creates ambiguity when recompiling old code, particularly when there's been heavy use of using namespace
s: the worst thing you can do in this space is allow using namespace
s in headers to escape the headers' scopes, such that an arbitrarily large amount of direct and indirect client code is unable to make their own decisions about which namespaces to use and how to manage ambiguities.
So, a leading ::
is one tool in the C++ programmer's toolbox to actively disambiguate a known clash, and/or eliminate the possibility of future ambiguity....