2010-08-17 13 views
8

zrobiłem następujący programKiedy potrzebujemy .template skonstruować

#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); 
} 

Powyższy program nie robi skompilować ponieważ display() jest funkcją członkiem szablon więc kwalifikacja .template przed display() musi być zrobione. Czy mam rację?

Ale kiedy zrobiłem następujący program

#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(); 
} 

Dlaczego k.func<char>(k); nie kompiluje nawet po złożeniu .template konstruktu?

+0

pełne i kompletne Odpowiedź na to pytanie można znaleźć we wpisie Comeau C++ Szablony FAQ [ "Czym jest' -> template', '.template' i' :: template' o składni"] (http://www.comeaucomputing.com/techtalk/templates/#templateprefix). –

+1

Utknąłem ... §5.2.5/1 mówi "Wyrażenie postfiksowe poprzedzone kropką lub strzałką ->, ** opcjonalnie po którym następuje szablon słowa kluczowego (14.8.1) **, a następnie identyfikator -expression, to wyrażenie postfiks. " Ale 14.8.1 wydaje się być niezwiązanym ze sobą, oprócz opisywania, w jaki sposób C++ jest w stanie rozwiązać szablony funkcji członków * bez * słowa kluczowego. Gdzie jest określone to słowo kluczowe? – Potatoswatter

+0

@Potatoswatter: Słowo kluczowe jest oczywiście określone w Tabeli 3..11. ;-) (Co ważniejsze, to jest dobre pytanie). –

Odpowiedz

14

< symbol oznacza zarówno „mniej niż” i "rozpocznij argumenty szablonu." Aby rozróżnić te dwa znaczenia, analizator składni musi wiedzieć, czy poprzedni identyfikator określa szablon, czy nie.

Na przykład rozważyć kod

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

Albo T::variable lub T::constant musi być szablon. Funkcja oznacza różne rzeczy w zależności co jest a co nie jest:

  1. albo T::constant dostaje w porównaniu do 3 i logiczny wynik staje się szablon argument T::variable<>
  2. lub T::constant<3> dostaje porównaniu x->variable.

disambiguate, słowo template jest wymagana przed każdym variable lub constant. Przypadek 1:

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

Przypadek 2:

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

byłoby miłe, jeśli słowo kluczowe były wymagane tylko w rzeczywistych sytuacjach niejednoznacznych (które są swego rodzaju rzadko), ale to sprawia, że ​​parser dużo łatwiejsze do napisania i zapobiega takim niespodziankom.

Dla standardese patrz 14.2/4:

Gdy nazwa członka szablon specjalizacji pojawia się po. lub -> w postfix ekspresji lub po zagnieżdżonego-NAME specyfikatorem w wykwalifikowanego-ID i postfix ekspresji lub wykwalifikowanego-id wyraźnie zależy na szablonach parametru (14.6.2), Nazwa szablonu elementu członkowskiego musi być poprzedzona prefiksem według szablonu słowa kluczowego. W przeciwnym razie przyjmuje się, że nazwa nie jest nazwą szablonu.

+0

+1 dla pierwszego przykładu: to jest naprawdę świetny fragment kodu do wykazania wrażliwości kontekstowej gramatyki C++ i dlaczego te słowa kluczowe są potrzebne. –

0

Pierwszy przykład kompiluje i działa dobrze dla mnie w VS 2010.

7

rozdział 5.1 C++ Templates wyjaśnia ten konstrukt szczegółowo

Poniższa funkcja ma problem

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

} 

Tutaj T = char i U = int

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

is bei ng zadzwonił. Jednak taka funkcja nie istnieje

Nawet w normalnych okolicznościach „char” jest zamienny do „int”, to nie posiada dobre dla wyraźnie określonych argumentów szablonu