Функция члена шаблона класса шаблона, вызванная из функции шаблона

Это не скомпилируется:

template<class X> struct A {
   template<int I> void f() {}
};

template<class T> void g()
{
   A<T> a;
   a.f<3>();  // Compilation fails here (Line 18)
}

int main(int argc, char *argv[])
{
   g<int>();  // Line 23
}

В компиляторе (gcc) говорится:

hhh.cpp: В функции 'void g()':

hhh.cpp: 18: ошибка: ожидаемое первичное выражение перед ')' токеном

hhh.cpp: В функции 'void g() [с T = int]':

hhh.cpp: 23: экземпляр здесь

hhh.cpp: 18: ошибка: недопустимое использование члена (вы забыли "&"?)

Может кто-нибудь объяснить, почему это? Есть ли способ заставить его работать?

Ответ 1

Попробуйте использовать следующий код:

template<class T> void g()
{
   A<T> a;
   a.template f<3>();  // add `template` keyword here
}

Согласно С++ '03 Standard 14.2/4:

Когда имя специализированного шаблона шаблона появляется после . или -> в постфиксном выражении или после вложенного имени-спецификатора в идентификаторе с квалифицированным идентификатором, а постфиксное выражение или квалифицированный идентификатор явно зависит по шаблону-параметру (14.6.2), имя шаблона члена должно иметь префикс с ключевым словом template. В противном случае предполагается, что имя называется не-шаблоном.

Будущему стандарту С++ по-прежнему требуется это ключевое слово согласно проекту n2857 14.3/4. Некоторые компиляторы имеют специальный режим, который позволяет скомпилировать исходный код без ошибок (Комо компилирует его в так называемом расслабленном режиме).

Ответ 2

Где определяется тип T?

Когда вы вызываете функцию g() в это время, тип T должен быть известен еще, готовьтесь к ошибке компилятора, говоря, что T undefined.

Ответ 3

Не могли бы вы указать, какой компилятор вы используете? Код в вопросе, с

int main() {
   g<int>();
}

добавлен скомпилированный без проблем с помощью cl.exe из Microsoft Visual Studio 9;

Не удалось выполнить различные версии g++, которые я пробовал, и онлайн-компилятор Comeau.