109
class C {
  using namespace std;  // error
};
namespace N {
  using namespace std; // ok
}
int main () {
  using namespace std; // ok
}

I want to know the motivation behind it.

Boann
  • 48,794
  • 16
  • 117
  • 146
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 1
    @pst: C# does not have anything like `using namespace`. C# allows something similar, but at file scope only. C++'s `using namespace` allows you to incorporate one namespace into another. – Billy ONeal Jun 13 '11 at 05:10
  • 2
    Duplicate of [this question](http://stackoverflow.com/questions/4362831/scoped-using-directive-within-a-struct-class-declaration)? – greatwolf Jun 13 '11 at 05:39

6 Answers6

38

I don't know exactly, but my guess is that allowing this at class scope could cause confusion:

namespace Hello
{
    typedef int World;
}

class Blah
{
    using namespace Hello;
public:
    World DoSomething();
}

//Should this be just World or Hello::World ?
World Blah::DoSomething()
{
    //Is the using namespace valid in here?
}

Since there is no obvious way of doing this, the standard just says you can't.

Now, the reason this is less confusing when we're talking namespace scopes:

namespace Hello
{
    typedef int World;
}

namespace Other
{
    using namespace Hello;
    World DoSomething();
}

//We are outside of any namespace, so we have to fully qualify everything. Therefore either of these are correct:

//Hello was imported into Other, so everything that was in Hello is also in Other. Therefore this is okay:
Other::World Other::DoSomething()
{
    //We're outside of a namespace; obviously the using namespace doesn't apply here.
    //EDIT: Apparently I was wrong about that... see comments. 
}

//The original type was Hello::World, so this is okay too.
Hello::World Other::DoSomething()
{
    //Ditto
}

namespace Other
{
    //namespace Hello has been imported into Other, and we are inside Other, so therefore we never need to qualify anything from Hello.
    //Therefore this is unambiguiously right
    World DoSomething()
    {
        //We're inside the namespace, obviously the using namespace does apply here.
    }
}
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • 6
    +1, I thought of this reason, but then same thing is applicable for `using namespace Hello;` inside other `namespace` also (and declaring `extern` function inside it). – iammilind Jun 13 '11 at 05:12
  • @iammilind: But the rules for that are much less confusing -- the one namespace is imported into the other namespace. Give me a sec to edit... – Billy ONeal Jun 13 '11 at 05:15
  • 12
    I don't think its confusing. C++ isn't about guesswork. If it were allowed, then the C++ ISO committee would have specified in the language specification. Then you wouldn't say its confusing. Otherwise one might say even this is confusing : http://www.ideone.com/npOeD ... but then the rule for such coding is specified in the spec. – Nawaz Jun 13 '11 at 05:19
  • @Nawaz: Hmm.. that's the opposite behavior compared to what I would expect. – Billy ONeal Jun 13 '11 at 05:24
  • @Billy: But then the rule is specified in the spec. Once you read the rule, then nothing is confusing. – Nawaz Jun 13 '11 at 05:26
  • @Nawaz: I would disagree with that. The spec is designed to do what people generally expect as reasonable behavior. That is, the spec is designed around people, not the other way around. – Billy ONeal Jun 13 '11 at 05:27
  • @Billy: Which people? What might confusing to you, may not be confusing for me. And once the rules are laid down in whitepaper, nothing is confusing then. As I said, C++ isn't about guesswork. – Nawaz Jun 13 '11 at 05:32
  • 1
    @Nawaz: Most users of the language. I never said C++ was about guesswork. I am saying that when the spec is designed, it's designed with what behavior most programmers will expect ahead of time. And the rules on paper often **are** confusing -- the standard attempts to be unambiguous but it does not always succeed. – Billy ONeal Jun 13 '11 at 05:41
  • 7
    On the first example, it should be: `Hello::World Blah::DoSomething()` or `Blah::World Blah::DoSomething()` (if it was allowed), the return type of a member function definition is not considered to be in the scope of the class in the language, so it has to be qualified. Consider the valid example of replacing the `using` with a `typedef Hello::World World;` at class scope. So there should be no surprises there. – David Rodríguez - dribeas Jun 13 '11 at 07:20
  • 1
    (Not relevant to the discussion at hand, but your typedef is backwards: it should be `typedef int World;`) – Adam Rosenfield Jun 13 '11 at 19:07
  • 1
    @Adam: Thanks! Gah! Wish it worked in the same order as assignments – Billy ONeal Jun 13 '11 at 19:10
  • 2
    If it were allowed, I believe it would be applied on a lexical scope level. I think this is the "obvious" solution with virtually no suprises. – Thomas Eding Nov 06 '12 at 19:51
  • +1 Thomas Eding, also this exact sort of ambiguity can already happen when importing a namespace into a function or alternate namespace. C++ has rules for dealing with that -- so why not within a class scope? – jstine Oct 20 '14 at 12:27
  • 1
    It is same like typedefing inside a class. If you typedef int MyNumber inside class MyClass, then you have to write MyClass::MyNumber MyClass::getNumber() {...}. Still typedef inside a class is allowed and namespace not? Illogical. – Youda008 Nov 06 '15 at 11:17
14

Because the C++ standard explicitly forbids it. From C++03 §7.3.4 [namespace.udir]:

using-directive:
    using namespace ::opt nested-name-specifieropt namespace-name ;

A using-directive shall not appear in class scope, but may appear in namespace scope or in block scope. [Note: when looking up a namespace-name in a using-directive, only namespace names are considered, see 3.4.6. ]

Why does the C++ standard forbid it? I don't know, ask a member of the ISO committee that approved the language standard.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • 77
    Yet another technically correct but useless answer; the worst kind. 1) more people than just the committee know the answer. 2) committee members participate in SO 3) if you don't know the answer (given the spirit of the question) why answer at all? – Catskul Aug 03 '18 at 17:36
  • 12
    @Catskul: it's not a useless answer. It's very useful to know that the standard explicitly addresses this and forbids it. It's also ironic that the most upvoted answer starts with "I don't know exactly". Also, the "standard forbids it" is not the same as "it isn't allowed because the compiler doesn't allow it", because the latter case would not answer follow-up questions like: is it a problem with my compiler? is the compiler not standard-compliant? is it a side effect of some other things that I'm not aware of? etc. – antonone Oct 15 '19 at 07:33
  • 1
    While it's not the "worst kind" of answer, it doesn't answer the question: why C++ forbids it. The OP already established that C++ forbids it. – Zendel Jan 01 '23 at 14:34
  • 1
    @antonone The question acknowledges that this is currently forbidden and explicitly asks for motivation behind it. Hence this answer is inadequate and doesn't answer the question. – Andrey Semashev Mar 13 '23 at 11:51
  • @AndreySemashev The question acknowledges that "it's forbidden", but still it could be forbidden by the compiler implementation. This answer makes it clear that it's forbidden by the standard. This helps with focusing on further search of the more precise answer. Ambiguity of the question in this area makes me think that the problem is in the question, not in the answer. – antonone Mar 13 '23 at 15:13
13

I believe that the rationale is that it would probably be confusing. Currently, while processing a class level identifier, lookup will first search in the class scope and then in the enclosing namespace. Allowing the using namespace at class level would have quite some side effects on how the lookup is now performed. In particular, it would have to be performed sometime between checking that particular class scope and checking the enclosing namespace. That is: 1) merge the class level and used namespace level lookups, 2) lookup the used namespace after the class scope but before any other class scope, 3) lookup the used namespace right before the enclosing namespace. 4) lookup merged with the enclosing namespace.

  1. This would make a big difference, where an identifier at class level would shadow any identifier in the enclosing namespace, but it would not shadow a used namespace. The effect would be strange, in that access to the used namespace from a class in a different namespace and from the same namespace would differ:

.

namespace A {
   void foo() {}
   struct B {
      struct foo {};
      void f() {
         foo();      // value initialize a A::B::foo object (current behavior)
      }
   };
}
struct C {
   using namespace A;
   struct foo {};
   void f() {
      foo();         // call A::foo
   }
};
  1. Lookup right after this class scope. This would have the strange effect of shadowing base classes' members. The current lookup does not mix class and namespace level lookups, and when performing class lookup it will go all the way to the base classes before considering the enclosing namespace. The behavior would be surprising in that it would not consider the namespace in a similar level to the enclosing namespace. Again, the used namespace would be prioritized over the enclosing namespace.

.

namespace A {
   void foo() {}
}
void bar() {}
struct base {
   void foo();
   void bar();
};
struct test : base {
   using namespace A;
   void f() {
      foo();           // A::foo()
      bar();           // base::bar()
   }
};
  1. Lookup right before the enclosing namespace. The problem with this approach is again that it would be surprising to many. Consider that the namespace is defined in a different translation unit, so that the following code cannot be seen all at once:

.

namespace A {
   void foo( int ) { std::cout << "int"; }
}
void foo( double ) { std::cout << "double"; }
struct test {
   using namespace A;
   void f() {
      foo( 5.0 );          // would print "int" if A is checked *before* the
                           // enclosing namespace
   }
};
  1. Merge with the enclosing namespace. This would have the exact same effect that applying the using declaration at the namespace level. It would not add any new value to that, but will on the other hand complicate lookup for compiler implementors. Namespace identifier lookup is now independent from where in the code the lookup is triggered. When inside a class, if lookup does not find the identifier at class scope it will fall back to namespace lookup, but that is exactly the same namespace lookup that is used in a function definition, there is no need to maintain new state. When the using declaration is found at namespace level, the contents of the used namespace are brought into that namespace for all lookups involving the namespace. If using namespace was allowed at class level, there would be different outcomes for namespace lookup of the exact same namespace depending on where the lookup was triggered from, and that would make the implementation of the lookup much more complex for no additional value.

Anyway, my recommendation is not to employ the using namespace declaration at all. It makes code simpler to reason with without having to keep all namespaces' contents in mind.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • 1
    I agree that using tends to create implicit oddities. But some libraries may get designed around the fact that `using` exists. By purposedly declaring things in deep nested long namespaces. E.g. `glm` does that, and uses multiple tricks to activate / present features when the client use `using`. – v.oddou Jun 14 '16 at 08:01
  • even right in the STL `using namespace std::placeholders` . c.f http://en.cppreference.com/w/cpp/utility/functional/bind – v.oddou Jun 20 '16 at 09:59
  • @v.oddou: `namespace ph = std::placeholders;` – David Rodríguez - dribeas Jun 20 '16 at 14:20
6

This is probably disallowed because of openness vs closedness.

  • Classes and structs in C++ are always closed entities. They are defined in exactly one place (although you can split declaration and implementation).
  • namespaces can be opened, re-opened and extended arbitrarily often.

Importing namespaces into classes would lead to funny cases like this:

namespace Foo {}

struct Bar { using namespace Foo; };

namespace Foo {
using Baz = int; // I've just extended `Bar` with a type alias!
void baz(); // I've just extended `Bar` with what looks like a static function!
// etc.
}
Daniel Steck
  • 1,083
  • 10
  • 12
  • 2
    Or we could just NOT define class members with the imported names. Let this construct add `namespace Foo` to the search order for all code inside the type definition of `struct Bar`, much like putting that line in every inline member function body, except that it would also be active for brace-or-equal initializers, etc. But it would still expire at the closing brace, the same as `using namespace` inside a member function body. Now there unfortunately doesn't seem to be any way to use Koenig-with-fallback lookup in a brace-or-equal initializer without polluting the enclosing namespace. – Ben Voigt Nov 12 '20 at 17:56
  • I don't get why this is a problem. You can use using namespace in functions that are only defined once (I know inlining kinda bypasses this, but that is not important here), but you can't in classes. – Hrvoje Jurić Feb 26 '21 at 12:36
  • @HrvojeJurić because functions don't (re-)export any names. Classes/structs do. – Daniel Steck Aug 10 '21 at 17:19
  • This answer's reasoning is incorrect. Structs/classes are defined once, and name lookup (for non-templates) is performed at the point of that definition. Any names that are introduced past that definition have no effect on the struct/class that is already defined. – Andrey Semashev Mar 13 '23 at 11:48
  • @AndreySemashev There's no well-defined notion of what is defined "before/after" the struct definition. Imagine multiple TUs each importing different headers together with a header defining the struct in question. – Daniel Steck Mar 23 '23 at 01:52
  • @DanielSteck > There's no well-defined notion of what is defined "before/after" the struct definition. -- Right, but the point is once the struct is defined, it's defined, and the definition is only valid if the names it uses (e.g. types and functions) are already defined before. Once the struct is defined, any future definitions have no effect on it. – Andrey Semashev Mar 23 '23 at 20:05
  • > Imagine multiple TUs each importing different headers together with a header defining the struct in question. -- And? If the names used by the struct are equivalent across all TUs then the struct is defined the same way in each TU. Otherwise, it's an ODR violation, and the program is not conforming to the C++ standard. – Andrey Semashev Mar 23 '23 at 20:07
  • If anything, what you're arguing here is that `using namepace Foo;` inside a struct (assuming re-export of names) would be ill-defined in the first place. I don't really see the point of bike-shedding the specifics of such a hypothetical feature. The whole point of my answer was that such a feature would be confusing at best, and potentially ill defined at worst. Your comments are supporting this. – Daniel Steck Mar 24 '23 at 16:49
4

I think it's a defect of the language. You may use workaround below. Keeping in mind this workaround, it is easy to suggest rules of names conflicts resolution for the case when the language will be changed.

namespace Hello
{
    typedef int World;
}
// surround the class (where we want to use namespace Hello)
// by auxiliary namespace (but don't use anonymous namespaces in h-files)
namespace Blah_namesp {
using namespace Hello;

class Blah
{
public:
    World DoSomething1();
    World DoSomething2();
    World DoSomething3();
};

World Blah::DoSomething1()
{
}

} // namespace Blah_namesp

// "extract" class from auxiliary namespace
using Blah_namesp::Blah;

Hello::World Blah::DoSomething2()
{
}
auto Blah::DoSomething3() -> World
{
}
-2

You can't use using namespace inside of a class, but what you can do is simply use #define and then #undef inside of the structure. It will act the exact same way as namespace a = b;

struct foo
{
#define new_namespace old_namespace
     
    void foo2()
    {
        new_namespace::do_something();
    }

#undef new_namespace 
};
SimpleY
  • 68
  • 5