marcv81
marcv81

Reputation: 876

What does "using namespace" do exactly?

The following C++ test code does not link (gcc 4.9.2, binutils 2.25). The error is In function 'main': undefined reference to 'X::test'.

01: #include <string>
02: #include <iostream>
03:
04: namespace X
05: {
06:     extern std::string test;
07: };
08:
09: using namespace X;
10: std::string test = "Test";
11:
12: int main()
13: {
14:    std::cout << X::test << std::endl;
15: }

Because of line 09, I was expecting line 10 to define the X::test variable declared on line 06. I believe that instead an unrelated test variable is declared and defined in the global namespace, hence the linking error.

Question: Could anyone please explain why my expectation was incorrect, and what is happening exactly?

Not the answer:

Upvotes: 22

Views: 7887

Answers (3)

Alex
Alex

Reputation: 10126

using namespace means you use definitions from the namespace you specified, but it doesn't mean that everything that you define is being defined in a namespace you use.

Logic of this behavior is pretty simple. Let's say we have the following example:

namespace X
{
    extern string test;
};

namespace Y
{
    extern string test;
};

using namespace X;
using namespace Y;

string test = "value";

Following your example logic, compiler just would not know in which namespace it should define test, so you would have to declare the namespace explicitly. In a real life it is defined in a global namespace.

In your specific case you define the test variable outside of the X namespace where it is declared as extern. Linker looks for definition of the X::test but doesn't find and as a result you see this error.

Upvotes: 9

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

Here is a declaration of variable test in namespace X.

04: namespace X
05: {
06:     extern std::string test;
07: };

It is not a definition of the variable. The variable must be also defined before it can be used to get its value.

You could make this declaration also a definition if you initialize the variable. For example

04: namespace X
05: {
06:     extern std::string test = "Test";
07: };

In this case the code would compile successfully.

In this statement

14:    std::cout << X::test << std::endl;

there is an access to the qualified name X::test. The compiler searches this name in namespace X as it is specified in the variable and finds the declaration. Now it needs to get the value of the variable but it is unable to find its definition.

In this statement

10: std::string test = "Test";

there is declared and defined variable test in the global namespace because it is declared outside any explicitly specified namespace.

You could write

10: std::string X::test = "Test";
                ^^^^^^^

instead of

10: std::string test = "Test";

if you want to define the variable declared in the namespace X.

As for the using directive then it introduces names declared in the specified namespace in the namespace where the directive is used.

For example If to write using unqualified name test

14:    std::cout << test << std::endl;
                    ^^^^^

then there will be an ambiguity because this name can refer to name X::test and ::test due to the using directive.

Upvotes: 3

The directive using namespace X; makes names from namespace X visible inside the namespace containing the directive. That is, when looking up a name n in that scope, X::n can be found. However, it will only be looked for if the compiler needs to look for it.

In your example, this declaration:

std::string test = "Test";

inside the global namespace makes perfect sense as-is. The name test is simply introduced, as with any other declaration. No need to look it up anywhere.

This would be an entirely different kettle of fish:

namespace X
{
  struct C
  {
    static std::string test;
  };
}

using namespace X;
std::string C::test = "Test";

In this code, the compiler needs to know what C is to make sense of the definition of C::test. It therefore does a name lookup of C, which indeed finds X::C thanks to the using directive.

Upvotes: 31

Related Questions