GCC в Linux ищет заранее объявленный метод в неправильном пространстве имен - PullRequest
0 голосов
/ 11 декабря 2018

Рассмотрим следующий сценарий:

Source.cpp

int add(int a, int b) { return a + b; } // function in global scope

Header.h

namespace ns
{
    class A
    {
    public:
        void do()
        {
            ...
            ...
            method();
            ...
            ...
        }
    private:
        int method()
        {
            ...
            ...
            int add(int a, int b); // forward declaration
            auto result = add(5, 10); // function call
            ...
            ...
            // do something with result
        }
    };
}

Вкл. Windows (MS Compiler) вышеописанное работает, как и ожидалось.

В Linux (GCC) это приводит к ошибке компоновщика, при которой метод add() сообщается как неопределенная ссылка .

Более того, ошибка указывает, что компилятор пытается найти add() в пространстве имен ns, но он четко определен в глобальном пространстве имен.

Включает ли GCCLinux ведет себя иначе, чем компилятор MS в Windows, когда связываете методы, которые объявлены вперед?Как мне решить эту проблему?

1 Ответ

0 голосов
/ 11 декабря 2018

Поиск имени компилятора MS не соответствует стандарту C ++ 11 при разрешении объявления int add(int a, int b) в теле ns::A::method к глобальному объявлению функции, определенной в Source.cpp.Это объявление находится в пространстве имен ns, и функция, которую оно должно объявить, является int ns::add(int a, int b), что, как жалуется GCC (или clang), не определено.

C ++11 § 3.5, п. 7:

Если не найдено, что объявление области блока сущности со связью ссылается на какое-то другое объявление, тогда эта сущность является членом внутреннего вложенного пространства имен.Однако такое объявление не вводит имя члена в его область пространства имен.[Пример:

namespace X {
    void p() {
        q(); // error: q not yet declared
        extern void q(); // q is a member of namespace X
    }
    ...
    ...

    void q() { /* ... */ } // definition of X::q
}

void q() { /* ... */ } // some other, unrelated q

конец примера]

У вас есть два варианта: -

  • Поднятьпрямое объявление int add(int a, int b) из пространства имен ns в глобальное пространство имен - то, где оно определено в source.cpp

  • Включение определения int add(int a, int b) в пространство имен ns:

Source.cpp

namespace ns {
    int add(int a, int b) { return a + b; }
}
...