Шаблон C++ получил
Только что мне пришлось пролистать сайт, чтобы узнать, почему функция-член шаблона класса выдает синтаксические ошибки:
template<class C> class F00 {
template<typename T> bar();
};
...
Foo<C> f;
f.bar<T>(); // syntax error here
Теперь я понимаю, что шаблонные скобки обрабатываются как операторы отношений. Чтобы сделать то, что предполагалось, необходим следующий причудливый синтаксис, см. Шаблоны: функция шаблона не очень хорошо работает с функцией-членом класса класса:
f.template bar<T>();
Какие еще странные аспекты и особенности шаблонов C++/C++, с которыми вы столкнулись, не были чем-то, что вы считаете общеизвестным?
4 ответа
Я получил путаницу в первый раз, когда унаследовал шаблонный класс от другого шаблонного класса:
template<typename T>
class Base {
int a;
};
template<typename T>
class Derived : public Base<T> {
void func() {
a++; // error! 'a' has not been declared
}
};
Проблема в том, что компилятор не знает, Base<T>
будет шаблоном по умолчанию или специализированным. Специализированная версия может не иметь int a
как член, поэтому компилятор не предполагает, что он доступен. Но вы можете сказать компилятору, что он будет там с using
директива:
template<typename T>
class Derived : public Base<T> {
using Base<T>::a;
void func() {
a++; // OK!
}
};
Кроме того, вы можете сделать явным, что вы используете член T
:
void func {
T::a++; // OK!
}
Это меня расстроило тогда:
#include <vector>
using std::vector;
struct foo {
template<typename U>
void vector();
};
int main() {
foo f;
f.vector<int>(); // ambiguous!
}
Последняя строка в main неоднозначна, потому что компилятор не только ищет vector
в foo
, но также как неквалифицированное имя, начинающееся изнутри main
, Так что находит оба std::vector
а также foo::vector
, Чтобы это исправить, нужно написать
f.foo::vector<int>();
GCC не заботится об этом и принимает приведенный выше код, выполняя интуитивно понятную вещь (вызывая член), другие компиляторы работают лучше и предупреждают, как comeau:
"ComeauTest.c", line 13: warning: ambiguous class member reference -- function
template "foo::vector" (declared at line 8) used in preference to
class template "std::vector" (declared at line 163 of
"stl_vector.h")
f.vector<int>(); // ambiguous!
Звезда вопросов о шаблонах здесь на SO: отсутствующее имя!
template <typename T>
class vector
{
public:
typedef T * iterator;
...
};
template <typename T>
void func()
{
vector<T>::iterator it; // this is not correct!
typename vector<T>::iterator it2; // this is correct.
}
Проблема здесь в том, что vector<T>::iterator
является зависимым именем: оно зависит от параметра шаблона. Как следствие, компилятор не знает, что iterator
обозначает тип; мы должны сказать ему с typename
ключевое слово.
То же самое касается шаблонных внутренних классов или шаблонных / статических функций: они должны быть устранены с помощью template
Ключевое слово, как отмечено в ОП.
template <typename T>
void func()
{
T::staticTemplateFunc<int>(); // ambiguous
T::template staticTemplateFunc<int>(); // ok
T t;
t.memberTemplateFunc<int>(); // ambiguous
t.template memberTemplateFunc<int>(); // ok
}
Определение функции-члена вне области видимости:
template <typename T>
class List { // a namespace scope class template
public:
template <typename T2> // a member function template
List (List<T2> const&); // (constructor)
…
};
template <typename T>
template <typename T2>
List<T>::List (List<T2> const& b) // an out-of-class member function
{ // template definition
…
}