Почему «Использование пространства имен x;»; Разве не допускается внутри класса/структуры?

StackOverflow https://stackoverflow.com/questions/6326805

Вопрос

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

Редактировать: Хочу знать мотивацию за этим.

Это было полезно?

Решение

Я не знаю точно, но я предполагаю, что разрешение на это в классе может вызвать путаницу:

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?
}

Поскольку нет очевидного способа сделать это, стандарт просто говорит, что вы не можете.

Теперь причина, по которой это менее сбивает с толку, когда мы говорим о областях пространства имен:

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.
    }
}

Другие советы

Потому что стандарт C ++ явно запрещает его. От c ++ 03 §7.3.4 [namespace.udir]:

Использование режиссера:
    using namespace ::Опт вложенное имен-спецификаторОпт имена пространства-имени ;

А Использование режиссера не появляется в сфере класса, но может появиться в области пространства имен или в сфере блока. [Примечание: при поиске имени имен имен в использовании направляющих, рассматриваются только имена пространства имен, см. 3.4.6.

Почему стандарт C ++ запрещает это? Я не знаю, спросите члена комитета ISO, который одобрил языковой стандарт.

Я считаю, что обоснование состоит в том, что это, вероятно, будет запутанным. В настоящее время при обработке идентификатора уровня класса поиск сначала будет искать в сфере сферы класса, а затем в пространстве имен. Позволяя using namespace На уровне класса было бы довольно некоторые побочные эффекты на то, как сейчас выполняется поиск. В частности, это должно быть выполнено где -то между проверкой этой конкретной сферы класса и проверкой пространства имен. То есть: 1) Объедините уровень класса и используемые поиск уровня имен, 2) поиск используемых имен пространство после Применение класса, но перед любой другой областью класса, 3) поиск используемого пространства имен прямо перед вмешательством пространства имен. 4) Поиск объединен с пространством имен.

  1. Это будет иметь большое значение, где идентификатор на уровне класса будет тень любой идентификатор в пространстве имен, но не будет тень а использовал Пространство имен. Эффект был бы странным в этом доступе к использовал Пространство имен из класса в другом пространстве имен и из одного и того же пространства имен будет отличаться:

.

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. Поиск сразу после этого класса. Это будет иметь странный эффект от членов классов затененных базовых классов. Текущий поиск не смешивает класс и поиск уровня имен, а при выполнении поиска класса он пройдет весь путь до базовых классов до Учитывая входное пространство имен. Поведение было бы удивительным тем, что оно не будет учитывать пространство имен на одинаковом уровне с пространством имен. Опять использовал Пространство имен будет приоритетным для пространства имен.

.

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. Поиск прямо перед вмешательством пространства имен. Проблема с этим подходом снова заключается в том, что это было бы удивительно для многих. Учтите, что пространство имен определено в другом блоке перевода, так что следующий код не может быть замечен одновременно:

.

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. Слияние с пространством имен. Это будет иметь тот же эффект, что и применение using Объявление на уровне пространства имен. Это не приведет к этому какую -либо новую ценность, но, с другой стороны, усложнит поиск для исполнителей компилятора. Поиск идентификатора пространства имен теперь не зависит от того, где в коде запускается поиск. В пределах класса, если поиск не найдет идентификатор в сфере сферы класса, он вернется к поиску пространства имен, но это точно тот же поиск пространства имен, который используется в определении функции, нет необходимости поддерживать новое состояние. Когда using Объявление находится на уровне пространства имен, содержимое использовал Пространство имен привел в это пространство имен для все поиск с участием пространства имен. Если using namespace Был разрешен на уровне класса, в зависимости от того же пространства имен будут разные результаты, в зависимости от того, откуда был вызван поиск, и это сделало бы реализацию поиска гораздо более сложной без дополнительной ценности.

В любом случае, моя рекомендация нет Чтобы использовать using namespace Декларация вообще. Это делает код более простым в рассуждении без необходимости помнить содержимое всех пространств имен.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top