Из раздела 7.3.4.2 стандарта c ++ 11:
с помощью директивы указывает, что имена в назначенном пространстве имен
может быть использован в объеме, в котором с помощью директивы появляется после
с помощью директивы. Во время поиска безоговорочного имени (3.4.1) имена
выглядят так, как будто они были объявлены в ближайшем окружении имен
который содержит как с помощью директивы и назначенное пространство имен. [
Примечание. В этом контексте «содержит» означает «содержит непосредственно или
косвенно». —Конечная записка]
Что именно означают второе и третье предложения? Пожалуйста, приведите пример.
Вот код, который я пытаюсь понять:
namespace A
{
int i = 7;
}
namespace B
{
using namespace A;
int i = i + 11;
}
int main(int argc, char * argv[])
{
std::cout << A::i << " " << B::i << std::endl;
return 0;
}
Он печатает «7 7», а не «7 18», как я ожидал.
Извините за опечатку, программа на самом деле печатает «7 11».
Устранение неопределенного поведения:
namespace A
{
int i = 7;
}
namespace B
{
using namespace A;
int tmp = i + 11;
int i = tmp;
}
#include <iostream>
int main()
{
std::cout << A::i << " " << B::i << std::endl;
return 0;
}
Смысл стандарта в том, что на линии
int tmp = i + 11;
имя i
появляется вближайшее окружающее пространство имен, которое содержит директиву using и назначенное пространство имен«; с помощью директивы появляется в namespace B
в то время как назначенное пространство имен namespace A
; Ближайшее пространство имен является глобальное пространство имен, так i
отображается как ::i
, Это означает, что если имя i
уже присутствует в глобальном пространстве имен, код неоднозначен.
Для более сложного примера:
namespace A {
namespace B {
namespace C {
int i = 4;
}
}
namespace D {
using namespace B::C;
namespace E {
int j = i;
}
}
}
На линии int j = i
, i
появляется в ближайшем окружающем пространстве имен директивы using (т.е. A::D
) и назначенное пространство имен (A::B::C
), который A
, Итак, внутри A::D
после использования директивы, а также в пределах A::D::E
безусловное имя i
может относиться к A::B::C::i
появляется как A::i
, следя за любым ::i
, конфликтуя с любым A::i
и быть в тени любого A::D::i
или же A::D::E::i
(в A::D::E
):
int i = 1; // shadowed by A::B::C::i appearing as A::i
namespace A {
int i = 2; // conflicts with A::B::C::i appearing as A::i
namespace B {
int i = 3; // irrelevant
namespace C {
int i = 4; // nominated; appears as A::i
}
}
namespace D {
int i = 5; // shadows A::B::C::i appearing as A::i
using namespace B::C;
namespace E {
int i = 6; // shadows A::B::C::i appearing as A::i
int j = i;
}
}
}
Обратите внимание, что только потому, что имя отображается как A::i
при поиске безоговорочного имени, это не значит, что оно на самом деле является там; квалифицированное имя A::i
будет продолжать ссылаться только на фактическое имя A::i
(если таковой существует).
using
утверждение в вашем коде не имеет значения. B::i
уже в области видимости, когда инициализатор для B::i
оценивается. Вы можете легко доказать это, удалив using
заявление; Ваш код должен скомпилироваться и работать точно так же. В любом случае значение B::i
оказывается неопределенным, потому что это зависит от неинициализированного значения (то есть значения, которое B::i
имел, когда инициализатор был оценен).