Столкновение пространства имен в C ++ - PullRequest
7 голосов
/ 16 июля 2009

Я не могу понять, почему этот кусок кода не компилируется:

namespace A {
        class F {};             // line 2
        class H : public F {};
}

namespace B {
        void F(A::H x);         // line 7
        void G(A::H x) {
                F(x);           // line 9
        }
}

Я использую gcc 4.3.3, и ошибка:

s3.cpp: In function ‘void B::G(A::H)’:
s3.cpp:2: error: ‘class A::F’ is not a function,
s3.cpp:7: error:   conflict with ‘void B::F(A::H)’
s3.cpp:9: error:   in call to ‘F’

Я думаю, что, поскольку в строке 9 нет префикса пространства имен, F(x) должно означать только B::F(x). Компилятор пытается привести x в свой суперкласс. В моем понимании этого не должно быть. Почему он это делает?

Ответы [ 4 ]

11 голосов
/ 16 июля 2009

Это потому, что компилятор будет искать функцию в том же пространстве имен, из которого ее аргументы. Компилятор нашел там A::F идентификатор, но это не функция. В результате вы получите ошибку.

Насколько я помню, это стандартное поведение.

3.4.2 Поиск имени в зависимости от аргумента Когда неквалифицированное имя используется в качестве выражения postfix в вызове функции (5.2.2), можно искать в других пространствах имен, не учитываемых при обычном неквалифицированном поиске (3.4.1), а объявления функций в пространстве имен области имен (11.4) нельзя в противном случае видимый может быть найден. Эти модификации поиска зависят от типов аргументов (и для аргументов шаблона шаблона - пространства имен аргумента шаблона).

Для каждого типа аргумента T в вызове функции существует набор из нуля или более связанных пространств имен и набор из нуля или более связанных классов, которые необходимо учитывать. Наборы пространств имен и классов полностью определяются типами аргументов функции (и пространством имен любого аргумента шаблона шаблона). Имена типов и объявления-использования, используемые для указания типов, не вносят свой вклад в этот набор. Наборы пространств имен и классов определяются следующим образом ...

Это правило позволяет вам написать следующий код:

std::vector<int> x;
// adding some data to x
//...

// now sort it
sort( x.begin(), x.end() ); // no need to write std::sort

И наконец: из-за Core Issue 218 некоторые компиляторы компилируют данный код без каких-либо ошибок.

4 голосов
/ 16 июля 2009

Вы уже пробовали использовать другие компиляторы? Здесь есть отчет об ошибке gcc , который приостановлен (что бы это ни значило).

РЕДАКТИРОВАТЬ: После некоторых исследований, я нашел эту более официальную ошибку .

1 голос
/ 16 июля 2009

Очень странно, я скопировал и вставил непосредственно в VS 2005, и я получил ошибку, которую я ожидал:

Ошибка 1, ошибка LNK2001: неразрешенный внешний символ "void __cdecl B :: F (class A :: H)"

Поскольку мы фактически не определили F (x) в пространстве имен B ... не уверены, почему Gcc выдает эту ошибку.

0 голосов
/ 16 июля 2009

Я только что попытался скомпилировать его в Visual Studio 2005, и он работал нормально. Интересно, это сломанная реализация Argument Dependent Lookup, где пространство имен из аргументов было случайно введено?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...