Search code examples
c++name-lookup

What is the difference between "using namespace Bar" and "using Bar::Foo"?


I have the code:

#include <iostream>

class Foo {

};

namespace Bar {
    struct Foo {

    };
}

namespace Baz
{
    void baz(const Foo &)
    {
        std::cout << "Hello";
    }
}

int main()
{
    Baz::baz(Bar::Foo());
}

Compiler can't figure out which Foo want to use and produces the error:

main.cpp: In function 'int main()':
main.cpp:23:19: error: invalid initialization of reference of type 'const Foo&' from expression of type 'Bar::Foo'
   23 |     Baz::baz(Bar::Foo());
      |                   ^~~~~
main.cpp:15:14: note: in passing argument 1 of 'void Baz::baz(const Foo&)'
   15 |     void baz(const Foo &)
      |   

Online compiler


Of course the simplest solution is to use either ::Foo or ::Baz::Foo, but I want to fix all possible ambiguities with O(1) lines of code.

My first idea was using namespace Bar inside Baz namespace:

namespace Baz
{
using namespace Baz;
//...

using-declaration: makes the symbol name from the namespace ns_name accessible for unqualified lookup as if declared in the same class scope, block scope, or namespace as where this using-declaration appears.

I expected that all Bar names become part of Baz namespace, and unqualified lookup prefers Baz::Foo. But for some reason it doesn't work

Online compiler


But using Bar::Foo;, in turn, does the trick. And that confuses me even more

namespace Baz
{
    using Bar::Foo;

Online compiler


So, my question is: What is the difference between using namespace Bar and using Bar::Foo in this case?


Solution

  • cppreference is your friend.

    As regards using namespace ns_name; it reads

    using-directive: From the point of view of unqualified name lookup of any name after a using-directive and until the end of the scope in which it appears, every name from ns_name is visible as if it were declared in the nearest enclosing namespace which contains both the using-directive and ns_name.

    As regards using ns_name::name; it reads

    using-declaration: makes the symbol name from the namespace ns_name accessible for unqualified lookup as if declared in the same class scope, block scope, or namespace as where this using-declaration appears.

    It seems complicated, but it isn't. Furthermore, learning things explained this way (which is close to standardese, I'd say) pays off when it comes to diving into the depths of C++.