Как избежать ошибки «не объявлено» в старой шаблонно-тяжелой библиотеке, не изменяя весь код для использования this->? - PullRequest
0 голосов
/ 11 ноября 2018

Я получаю сообщение об ошибке «не было объявлено в этой области» при попытке скомпилировать библиотеку, содержащую сильно шаблонный код. Похоже, код был разработан с использованием gcc-2.95 и (как мне сказали) скомпилировался около четырех лет назад. Как я обнаружил в StackOverflow и C ++ - FAQ , код действительно должен завершиться сбоем и, похоже, полагается на несоответствующую компиляцию.

Пример минимального воспроизведения, компилируйте с gcc -c example.cpp:

// file: example.cpp
template <typename T>
class Base {
  protected:
    int i;
};

template <typename T>
class Derived : protected Base<T> {
  public:
    void f() {
        // i = 5;     // Error: i was not declared in this scope
        this->i = 5;  // compiles
    }
};

У меня вопрос : Как мне скомпилировать эту библиотеку, используя более свежие компиляторы?

Код библиотеки повсеместно использует ошибочный синтаксис (i = 5), поэтому я бы предпочел избегать ручного изменения всей библиотеки на «this-> i = 5». Приведенные ссылки предполагают использование операторов, но хотя это уменьшит мою работу, мой предпочтительный метод не будет включать никаких изменений кода, а вынудит компилятор к старому поведению «предполагать это» для этих переменных. Я не мог найти переключатель компилятора для этой ситуации, -std=c++98, -fpermissive и т. Д. Не работали.

Цитата из C ++ - FAQ:

Возможно, удивительно, следующий код не является допустимым C ++, хотя некоторые компиляторы принимают его:

Я также пытался использовать CLang ++, с теми же результатами. Какие компиляторы примут этот код без изменений?

Редактировать: Добавлена ​​информация о -fpermissive, как предложил Брайан

1 Ответ

0 голосов
/ 11 ноября 2018

К сожалению, как сказал @Mat в комментариях, единственная жизнеспособная альтернатива здесь - это исправить код (и вы показали, что уже знаете, как это сделать).

Это результат двухфазного поиска имени, поэтому, чтобы компилятор принял его, вам нужен тот, который не реализует двухфазный поиск имени. С компилятором Microsoft вы можете использовать флаг - Zc:twoPhase-, чтобы получить старое поведение с текущим компилятором (то есть, чтобы компилятор принял ваш код как есть).

g ++ имел двухфазный поиск имен, достаточно корректный, начиная с g ++ 4.7, если память не изменяет. Я был бы довольно уверен, что все серии g ++ 3.x по-прежнему будут принимать ваш код, и, вероятно, ранняя версия g ++ 4.x также будет, но я уверен, что g ++ 4.7 и более поздние отклонят его.

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

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