namespaces — область действия c ++ с использованием директивы

Из раздела 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».

4

Решение

Устранение неопределенного поведения:

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::iA::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 (если таковой существует).

4

Другие решения

using утверждение в вашем коде не имеет значения. B::i уже в области видимости, когда инициализатор для B::i оценивается. Вы можете легко доказать это, удалив using заявление; Ваш код должен скомпилироваться и работать точно так же. В любом случае значение B::i оказывается неопределенным, потому что это зависит от неинициализированного значения (то есть значения, которое B::i имел, когда инициализатор был оценен).

5

По вопросам рекламы [email protected]