Лучший синтаксис C++ для шаблонных определений типов базового класса и функций?

У меня есть код, который компилирует прекрасный с VC9 (Microsoft Visual C++ 2 008 SP1), но не с GCC 4.2 (на Mac, если это имеет значение). Если я наваливаю достаточно спецификаторов и ключевых слов, я могу вынудить это работать в GCC, но это не кажется правильным.

Вот минимальный пример кода, показывающий мои проблемы:

template< typename N >
struct B {
    typedef N n_type;                     // can derived class access typedef?
    void foo() {}                         // can derived class access function?
};

template< typename N >
struct D : public B<N> {

    typedef B<N> b_type;
    typedef typename b_type::n_type bn_type;

    void f1( n_type ) {}                  // ERROR: 'n_type' has not been
                                          // declared

    void f2( typename B<N>::n_type ) {}   // OK, verbose

    void f3( b_type::n_type ) {}          // ERROR: 'struct B<N>::n_type' is 
                                          // not a type

    void f4( typename b_type::n_type ) {} // OK, verbose

    void f5( bn_type ) {}                 // OK, verbose typedefs

    void f6() { foo(); }                  // ERROR: there are no arguments to
                                          // 'foo' that depend on a template
                                          // parameter, so a declaration of
                                          // 'foo' must be available

    void f7() { b_type::foo(); }          // OK, verbose

};

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

8
задан jwfearn 19 January 2010 в 22:13
поделиться

4 ответа

Неужели я ошибаюсь, ожидая, что класс-шаблон, производный от другого класса-шаблона, сможет напрямую использовать наследуемые typedefs и функции?

Да, в общем-то, это не сработает так, как вы ожидаете. Правила поиска имен C++ предусматривают, что поиск имени в шаблонных базовых классах осуществляется только в том случае, если оно зависит от параметра шаблона (если это "зависимое имя"). Если имя не зависит от параметра шаблона, то поиск в нем не производится. (См. также this C++ FAQ Lite entry)

Для вызова функций из зависимого базового класса самым простым способом является использование this->, так как this всегда неявно является зависимым именем:

void f6() { this->foo(); }
9
ответ дан 5 December 2019 в 11:24
поделиться

Существует несколько различий на высоком уровне, которые приходят к моему уме. Некоторые из них являются обобщениями и должны быть префиксированы «часто ...» или «некоторыми компиляторами ...», но ради читабельности я оставлю это.

  • Компиляция C / C ++ не читает никакой информации из двоичных файлов, но считывает определения метода / типа, только из файлов заголовка, которые необходимо проанализировать в полном объеме (исключение: предложенные заголовки)
  • C / C ++ Компиляция включает в себя -Поцессорный шаг, который может сделать широкий спектр текстовой замены (что делает предварительный компиляцию заголовка сложнее)
  • Синтаксис C ++ - это намного сложнее, чем синтаксис Java
  • Система типа C ++ - это намного больше Комплекс, чем система Java типа
  • C ++ Компиляция обычно производит родной ассемблерный код, который является гораздо более сложным для получения, чем относительно простой байтовый код
  • C ++ компиляторы должны делать оптимизации, потому что нет никакой другой вещи, которая будет сделать их. Компилятор Java в значительной степени простают простую 1: 1 перевод исходного кода Java в код байта Java, на этот шаг не выполняется никаких оптимизаций (это оставлено для выполнения JVM).
  • C ++ имеет язык шаблона, который загорелся! (Столь строго говоря, C ++ код должен быть запустить для создания исполняемого кода, и компилятор C ++ необходимо будет решить проблему завершения, чтобы сказать вам, если ARBITRARY C ++ CODE компилируется).
-121--3090714-

см. В C ++ FAQ Lite § 35.18-20 и FAQ C ++ C ++ FAQ .

Двухфазное имя поиска - это сложная часть C ++, что многие компиляторы (и кодеры) ошибаются. Достаточно сказать, GCC является более правильным (согласно спецификации C ++), чем MSVC здесь, и нет, нет лучшего способа сделать то, что вы хотите.

3
ответ дан 5 December 2019 в 11:24
поделиться

нет никакого типа n_type. Существует (или может быть) тип с таким именем зависит от N. Так что нет, вы не можете делать то, что хотите.

2
ответ дан 5 December 2019 в 11:24
поделиться

Вот несколько ссылок, которые могут помочь понять, почему ему нужна Tymename ключевые слова, которые будут использоваться:

  1. Блог STAN Lippman
  2. COMEAUCOUCLOWFLOW.COM
  3. COMEAUCOUCUTING

, кажется, что GCC «делает это правильно»

1
ответ дан 5 December 2019 в 11:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: