У меня есть код, который компилирует прекрасный с 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
};
Разве я неправ ожидать, что шаблонный класс, полученный из другого шаблонного класса, сможет использовать наследованные определения типов и функции непосредственно? Существует ли лучший способ сделать это, чем, что я придумал до сих пор?
Неужели я ошибаюсь, ожидая, что класс-шаблон, производный от другого класса-шаблона, сможет напрямую использовать наследуемые typedefs и функции?
Да, в общем-то, это не сработает так, как вы ожидаете. Правила поиска имен C++ предусматривают, что поиск имени в шаблонных базовых классах осуществляется только в том случае, если оно зависит от параметра шаблона (если это "зависимое имя"). Если имя не зависит от параметра шаблона, то поиск в нем не производится. (См. также this C++ FAQ Lite entry)
Для вызова функций из зависимого базового класса самым простым способом является использование this->
, так как this
всегда неявно является зависимым именем:
void f6() { this->foo(); }
Существует несколько различий на высоком уровне, которые приходят к моему уме. Некоторые из них являются обобщениями и должны быть префиксированы «часто ...» или «некоторыми компиляторами ...», но ради читабельности я оставлю это.
см. В C ++ FAQ Lite § 35.18-20 и FAQ C ++ C ++ FAQ .
Двухфазное имя поиска - это сложная часть C ++, что многие компиляторы (и кодеры) ошибаются. Достаточно сказать, GCC является более правильным (согласно спецификации C ++), чем MSVC здесь, и нет, нет лучшего способа сделать то, что вы хотите.
нет никакого типа n_type. Существует (или может быть) тип с таким именем зависит от N. Так что нет, вы не можете делать то, что хотите.
Вот несколько ссылок, которые могут помочь понять, почему ему нужна Tymename
ключевые слова, которые будут использоваться:
, кажется, что GCC «делает это правильно»