Когда нам нужна конструкция .template - PullRequest
9 голосов
/ 17 августа 2010

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

#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<char>(k); не компилируется даже после предоставления конструкции .template?

Ответы [ 4 ]

22 голосов
/ 18 августа 2010

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

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

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->variable.

Для устранения неоднозначности ключевое слово template необходимо указывать перед variable или constant. Дело 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), имя шаблона участника должно быть префиксом по шаблону ключевого слова. В противном случае имя предполагается, чтобы назвать без шаблона.

7 голосов
/ 17 августа 2010

Раздел 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', это не подходит для явно указанных аргументов шаблона

0 голосов
/ 17 августа 2010

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

0 голосов
/ 17 августа 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...