Конфликты имен не обнаружены при использовании псевдонимов

Это продолжение этого вопроса. Рассмотрим следующий пример:

#include <iostream>

namespace MyProject {
    class string {
        public: string() { std::cout << "Callin string constructor" << std::endl; }
    };
}

namespace Other {
    class string {};
}

namespace MyProject {
    using Other::string;
}

namespace MyProject {
    void useString() {
        const string s;
    }
}

int main() {
    MyProject::useString();
}

Здесь компилятор правильно выдает ошибку в строке using Other::string, жалуясь на то, что объявление для string уже существует в этом пространстве имен, исходя из предыдущего определения class string.

Теперь подумайте об этом:

#include <iostream>

namespace MyProject {
    class string {
        public: string() { std::cout << "Callin string constructor" << std::endl; }
    };
}

namespace Other {
    class something {};
    using string = something;
}

namespace MyProject {
    using Other::string;
}

namespace MyProject {
    void useString() {
        const string s;
    }
}

int main() {
    MyProject::useString();
}

Здесь нет ошибки компиляции: мне удалось скрыть мое предыдущее объявление string новым.

  • Почему во втором случае нет ошибки? Это потому, что using string = something не является фактическим объявлением, так как это псевдоним, а настоящее объявление предназначено для имени something, и компилятор может обнаружить конфликты только между фактическими объявлениями, поэтому в этом случае он подумал бы, что Я действительно объявляю something и string, и вы согласны с этим?

  • Разве это не очень опасно? Я имею в виду, что если эти вещи происходят в отдельных файлах заголовков без ведома программиста, он/она может в конечном итоге использовать идентификатор, который может быть чем-то совершенно отличным от того, что он/она думает, и компилятор ничего не скажет...


person swahnee    schedule 04.10.2016    source источник
comment
Какой компилятор/версия? Clang 3.8+ отклоняет этот код как неоднозначный (не на using, а при объявлении const string s).   -  person Holt    schedule 04.10.2016
comment
@Хорошо, я проверял это на g++ 4.9.2.   -  person swahnee    schedule 04.10.2016
comment
vc++ также принимает код. Похоже, что все основные компиляторы ошибаются, см. 7.3.3/13. Поскольку использование-объявления является объявлением, ограничения на объявления с тем же именем в той же области объявлений (3.3) также применяются к использованию-объявлений.   -  person n. 1.8e9-where's-my-share m.    schedule 04.10.2016