What does it mean if namespace in C++ is qualified with ::
? For example ::testing::Test
.
::
is the scope resolution operator. It always means "search the global namespace for the symbol on the right." For example:
namespace testing {
int a = 1;
}
namespace foo {
namespace testing {
int a = 2;
}
int b = ::testing::a; // b has the value 1
int c = testing::a; // c has the value 2
}
This invokes something called the qualified name lookup:
$3.4.3/1 - "The name of a class or namespace member can be referred to after the :: scope resolution operator (5.1) applied to a nested-name-specifier that nominates its class or namespace. During the lookup for a name preceding the :: scope resolution operator, object, function, and enumerator names are ignored. If the name found is not a class-name (clause 9) or namespace-name (7.3.1), the program is ill-formed."
I if you precede a variable name with ::, it resolves the variable to the global scope. In this way, you can have both a local variable testing and global variable testing and differentiate between them.
#include <iostream>
using namespace std;
int testing = 37;
int main()
{
int testing = 42;
cout << ::testing << ' ' << testing << endl;
}
Output will be 37 42
It means that the testing
namespace being referred to is the one off the global namespace, rather than another nested namespace named testing
.
Consider the following corner case, and probably an example of bad design:
namespace foo
{
struct gizmo{int n_;};
namespace bar
{
namespace foo
{
float f_;
};
};
};
int main()
{
using namespace foo::bar;
::foo::gizmo g;
g.n_;
}
There are 2 namespaces named foo
. One is the top-level hanging off of the "global" namespace, and another one is nested within foo::bar
. then we go on to using namespace foo::bar
, meaning any unqualified reference to gizmo
will pick up the one in foo::bar::foo
. If we actually want the one in foo
then we can use an explicit qualification to do so:
::foo::gizmo
If ::
is used on the left side it means the global scope.
If you want an analogy with the filesystem, testing::Test
would be a kind of relative path (with respect of König lookup) whereas ::testing::Test
would be an absolute path. I hope this analogy makes it clearer and doesn't mess up your mind :-).