Когда нам нужна конструкция .template

Я создал следующую программу

#include <iostream>
#include <typeinfo>
template<class T>
struct Class
{
    template<class U>
    void display(){

        std::cout<<typeid(U).name()<<std::endl;
        return ;
    }

};


template<class T,class U>
void func(Class<T>k)
{
    k.display<U>(); 

}

int main()
{
    Class<int> d;
    func<int,double>(d);
}

Вышеуказанная программа не компилируется, поскольку display () является шаблоном функция-член, поэтому необходимо выполнить квалификацию .template перед display () . Я прав?

Но когда я сделал следующую программу

#include <iostream>
#include <typeinfo>

template<typename T>
class myClass
{
    T dummy;
    /*******/
public:
    template<typename U>
    void func(myClass<U> obj);

};

template<typename T>
template<typename U>

void myClass<T>::func(myClass<U> obj)
{
    std::cout<<typeid(obj).name()<<std::endl;
}
template<class T,class U>
void func2(myClass<T>k)
{
    k.template func<U>(k); //even it does not compile

}
int main()
{
    myClass<char> d;
    func2<char,int>(d);
    std::cin.get();
}

, почему k.func (k); не компилируется даже после предоставления конструкции .template ?

9
задан Prasoon Saurav 17 August 2010 в 13:12
поделиться

4 ответа

Символ < означает как «меньше», так и «начало аргументов шаблона». Чтобы различать эти два значения, синтаксический анализатор должен знать, называет ли предыдущий идентификатор шаблон или нет.

Например, рассмотрим код

template< class T >
void f( T &x ) {
    x->variable < T::constant < 3 >;
}

Либо T :: variable , либо T :: constant должны быть шаблоном. Функция означает разные вещи в зависимости от того, что есть, а что нет:

  1. либо T :: constant сравнивается с 3, и логический результат становится аргументом шаблона для T :: variable <>
  2. или T :: constant <3> сравнивается с x-> переменной .

Чтобы устранить неоднозначность, ключевое слово шаблона требуется перед переменной или константой . Случай 1:

template< class T >
void f( T &x ) {
    x->template variable < T::constant < 3 >;
}

Случай 2:

template< class T >
void f( T &x ) {
    x->variable < T::template constant < 3 >;
}

Было бы неплохо, если бы ключевое слово требовалось только в реальных неоднозначных ситуациях (что бывает редко), но это значительно упрощает написание синтаксического анализатора и предотвращает такие проблемы. застать вас врасплох.

Стандартные см. 14.2 / 4:

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

24
ответ дан 4 December 2019 в 07:13
поделиться

Раздел 5.1 Шаблонов C ++ подробно объясняет эту конструкцию

У функции ниже есть проблема

template<class T,class U> 
void func2(myClass<T> k) 
{ 
    k.template func<U>(k); //even it does not compile 

} 

Здесь вызывается T = char и U = int

myclass<char>::func<int>(myclass<char>) 

. Однако такой функции не существует

. Хотя в обычных обстоятельствах char можно преобразовать в int, это не работает для явно указанных аргументов шаблона

7
ответ дан 4 December 2019 в 07:13
поделиться

Стандарт требует ключевых слов template или typename для устранения неоднозначности вещей, которые зависят от контекста шаблона .

0
ответ дан 4 December 2019 в 07:13
поделиться

Первый пример компилируется и отлично работает в VS 2010.

0
ответ дан 4 December 2019 в 07:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: