Лучший синтаксис C ++ для шаблонных базовых классов typedefs и функций? - PullRequest
8 голосов
/ 19 января 2010

У меня есть код, который прекрасно компилируется с VC9 (Microsoft Visual C ++ 2008 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

};

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

Ответы [ 4 ]

9 голосов
/ 19 января 2010

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

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

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

void f6() { this->foo(); }
3 голосов
/ 19 января 2010

См. C ++ FAQ Lite § 35.18-20 и C ++ Templates FAQ .

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

2 голосов
/ 19 января 2010

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

1 голос
/ 19 января 2010

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

  1. Блог Стэна Липпмана
  2. StackOverflow.com
  3. comeaucomputing

Кажется, что GCC "делает все правильно"

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