разрешение typedef через пространства имен - PullRequest
9 голосов
/ 18 февраля 2011

Я в настоящее время путаюсь с тем, как операторы using (namespace) работают в C ++.

У меня есть:

//somewhere in included headers
typedef unsigned int uint;

namespace mine {
    typedef unsigned int uint;
}
namespace other {
    using namespace mine;
    void foobar () {
        uint offender = i;
    }
}

Результаты в (перефразированном):
ссылка на «uint» неоднозначна. кандидаты
typedef unsigned int uint
и
typedef unsigned int mine :: uint

Тем временем, когда я делаю

namespace other {
    using namespace mine;
    using mine::uint;

    void foobar () {
        uint offender = i;
    }
}

Все отлично работает. Мне кажется странным, что «используя идентификатор ;» изменяет видимость другого определения typedef (скрывает глобальное определение?). Может кто-нибудь указать мне, какие правила в C ++ определяют разрешение typedefs в пространствах имен?

Ответы [ 4 ]

12 голосов
/ 18 февраля 2011

Имя, которое становится видимым с помощью директивы using , появляется в ближайшей охватывающей области, содержащей [- прямо или косвенно]] директиву using using и назначенное пространство имен.(7.3.4 [namespace.udir])

Это означает, что оба uint объявления появляются в глобальной области пространства имен при просмотре после using-директивы в other.

A using-декларация , как и любое другое объявление, объявляет имя в области видимости, в которой оно появляется.Вот почему во втором примере using mine::uint; скрывает uint, введенный using namespace mine;, поскольку последний, кажется, происходит из глобальной области видимости.

4 голосов
/ 18 февраля 2011

Ваш оригинальный код сбивает с толку компилятор, потому что uint может быть либо

::uint

, либо

::mine::uint

, поэтому компилятор выдает это сообщение об ошибке.В «исправлении» использование mine::uint явно указывало на предпочтение ::mine::uint.

Однако конфликта ИМО следует избегать.Это делает код так трудно поддерживать.

1 голос
/ 18 февраля 2011

Я не могу процитировать для вас главы и стихи, но для меня это имеет смысл. Если компилятор не может найти символ uint в текущем пространстве имен, он смотрит в другие пространства имен, чтобы узнать, сможет ли он найти символ там. Поскольку он находит его в двух других пространствах имен, он неоднозначен.

Когда вы сказали using mine::uint, вы импортировали этот символ в текущий блок, поэтому он был найден до того, как нужно проверить другие пространства имен.

0 голосов
/ 18 февраля 2011

Это не скрывает глобальный. Вот почему у вас есть двусмысленность.

...