Ошибка компиляции g ++ другой вещи, которая работает в msvs - PullRequest
2 голосов
/ 02 февраля 2010

Привет, ребята. Я портирую некоторый код из проекта, в основном разработанного в MSVS, на использование g ++. Я обнаружил много небольших различий, в основном то, что MSVS позволяет, а g ++ - нет. Обычно это что-то, связанное со стандартами c ++, вещи, которые MSVS позволяет скользить, но мне трудно понять, что не так с одним конкретным разделом.

g ++ испытывает проблемы при сопоставлении вызова оператора! =, Но только в определенном контексте. Поиск оператора! = Для определенного вложенного класса работает, если класс хостинга не является шаблоном. Если я превращу хостинг-класс в шаблон класса, все сломается. Я либо пропускаю что-то фундаментальное для c ++, либо g ++ делает что-то не так.

Я научился не плакать "Ошибка компилятора!" слишком часто, поэтому я хотел посмотреть, сможет ли кто-нибудь здесь увидеть, чего мне не хватает.

Этот работающий пример показывает рабочую версию без шаблона, а затем сломанную версию шаблона. g ++ - версия дает: g ++ (Ubuntu 4.4.1-4ubuntu9) 4.4.1

Рабочая справочная версия без шаблонов

namespace Works {

struct host {
    struct iterator {};
    iterator op();
};

bool operator != (host::iterator const& a0, host::iterator const& a1);

bool f() {
    return host().op() != host().op();
}

} // namespace Works

Разбитая версия с шаблонами

namespace Broken {

template <typename T>
struct host {
    struct iterator {};
    iterator op();
};

template <typename T>
bool operator != (typename host<T>::iterator const& a0, 
                   typename host<T>::iterator const& a1);

bool f() {
    return host<int>().op() != host<int>().op();
}

} // namespace Broken

Версия шаблона не работает с ошибками:

Main.cpp: In function ‘bool Broken::f()’:
Main.cpp:50: error: no match for ‘operator!=’ in ‘Broken::host<int>().Broken::host<T>::op [with T = int]() != Broken::host<int>().Broken::host<T>::op [with T = int]()’

Ответы [ 3 ]

5 голосов
/ 02 февраля 2010

Это не работает ни в msvc, ни в gcc.

Проблема в том, что в host<T>::iterator, T находится в не выводимом контексте. Поскольку ни один из параметров не позволяет вывести T, шаблон функции не может быть создан.

Вот почему вы обычно определяете перегруженные операторы внутри класса.

struct iterator
{
    friend bool operator != (iterator const & lhs, iterator const & rhs)
    {
        return false;
    }
};
0 голосов
/ 02 февраля 2010

Составляя ответ @ avakar, я получил код для правильной работы, хотя он немного странный:

namespace Broken {

template <typename T> struct host;

template <typename T>
bool operator != (typename host<T>::iterator const& a0,
                  typename host<T>::iterator const& a1);

template <typename T>
struct host {
    struct iterator {
       friend bool operator !=(iterator const & lhs, iterator const & rhs) {
          return operator !=<int>(lhs, rhs);
       }
    };
    iterator op();
};

bool f() {
    // The following does indeed end up calling the operator != you want it to call.  I
    // have a slightly different version in which I tested this.
    return host<int>().op() != host<int>().op();
}

} // namespace Broken

Это решает проблему, заключающуюся в том, что аргументы шаблона на верхний уровень operator != не могут быть выведены путем вызова его с явным аргументом шаблона из функции-друга. Требуется предварительное объявление шаблона host.

0 голосов
/ 02 февраля 2010

я ударил похожую вещь. Предполагается, что перегрузки операторов C ++ принимают константные входные данные. msvc позволит вам использовать неконстантные входы. G ++ настаивает, что они постоянны

...