Ошибка компилятора g ++ с шаблонным членом базового класса - PullRequest
3 голосов
/ 25 января 2012

Я пытаюсь скомпилировать код Microsoft Visual C ++, используя g ++.Теперь я столкнулся с ошибкой компилятора, которую я действительно не могу понять.(Упрощенный) код выглядит следующим образом:

template<int X> struct A {
    template<class Ret> static Ret call() {
        return 0;
    }
};

template<int X> struct B : A<X> {
    int f() {
        return A<X>::call<int>();
    }
};

Когда я пытаюсь скомпилировать это с g ++ (версия 4.4.5), я получаю следующую ошибку:

main.cpp: In member function int B<X>::f(): 
main.cpp:16: error: expected primary-expression before int 
main.cpp:16: error: expected ; before int
main.cpp:16: error: expected unqualified-id before > token

Если яудалите тип шаблона (Ret) из метода A :: call, код компилируется просто отлично.Кто-нибудь может увидеть, что здесь не так?

Спасибо!

Ответы [ 3 ]

5 голосов
/ 25 января 2012

A является шаблоном, и, не зная X, компилятор не может определить содержимое A<X>. Тем более, что он не знает, что call станет шаблоном.

Чтобы сообщить это компилятору, вы должны использовать ключевое слово template:

template<int X> struct B : A<X> {
    int f() {
        return A<X>::template call<int>();
    }
};
5 голосов
/ 25 января 2012

Вам необходимо ключевое слово template:

return A<X>::template call<int>();

call - это зависимое имя, означающее, что его значение зависит от параметра шаблона, который неизвестен, когда процесс компилятора f().Необходимо указать, что call является шаблоном функции, добавив к нему префикс с ключевым словом template.

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

template <typename T>
struct A { typedef int type; };

template <typename T>
void f()
{
    typename A<T>::type i = 0; // notice "typename" here
}

И иногда вам даже нужно смешать оба:

template <typename T>
struct A
{
    template <typename U>
    struct inner { };
};

template <typename T>
void f()
{
    typename A<T>::template inner<int> var;
}

Использование этих двух ключевых слов подробно объясняется в ответах на этот вопрос.вопрос: Где и почему я должен поставить ключевые слова «template» и «typename»? (спасибо @ Björn Pollex за поиск ссылки).

3 голосов
/ 25 января 2012

Вы должны указать, что вызываемая вами функция является шаблоном, поскольку она является частью класса шаблона. Компилятор не знает, что у любого данного A<X> есть функция шаблона с именем call, и поэтому вам нужно помочь ему.

template<int X> struct B : A<X> {
    int f() {
        return A<X>::template call<int>();
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...