2010-08-17 8 views
8
konstruieren

Ich habe das folgende ProgrammWann brauchen wir ein .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); 
} 

Das obige Programm doesn nicht kompiliert, da display() eine Template-Elementfunktion ist so eine Qualifikation von .template vor display() muss getan werden. Habe ich recht?

Aber wenn ich mache das folgende Programm

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

Warum k.func<char>(k); nicht einmal kompilieren, nachdem ein .template Konstrukt zu geben?

+0

Eine vollständige Antwort auf diese Frage finden Sie im Comeau C++ - Vorlagen-FAQ-Eintrag, ["Was ist das' -> Template', '.template' und' :: template' Syntax über? "] (http://www.comeaucomputing.com/techtalk/templates/#templateprefix). –

+1

Ich stecke fest ... §5.2.5/1 sagt "Ein Postfix Ausdruck gefolgt von einem Punkt. Oder einem Pfeil ->, ** optional gefolgt von der Schlüsselwort Vorlage (14.8.1) **, gefolgt von einer ID -expression, ist ein Postfix-Ausdruck. " Aber 14.8.1 scheint nicht verwandt zu sein, abgesehen davon, dass beschrieben wird, wie C++ Memberfunktionsvorlagen * ohne * das Schlüsselwort auflösen kann. Wo wird dieses Keyword angegeben? – Potatoswatter

+0

@Potatoswatter: Das Schlüsselwort ist natürlich in §2.11 Tabelle 3 angegeben. ;-) (Auf eine ernstere Anmerkung, das ist eine gute Frage). –

Antwort

14

Das < Symbol bedeutet sowohl „kleiner als“ und "Beginne Vorlagenargumente." Um zwischen diesen beiden Bedeutungen unterscheiden zu können, muss der Parser wissen, ob der vorangehende Bezeichner eine Vorlage benennt oder nicht.

Zum Beispiel betrachten den Code

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

Entweder T::variable oder T::constant muss eine Vorlage sein. Die Funktion bedeutet, verschiedene Dinge je nachdem, welche ist und welche nicht:

  1. entweder T::constant wird im Vergleich zu 3 und das Boolesche Ergebnis wird ein Template-Argument zu T::variable<>
  2. oder T::constant<3> wird zu x->variable verglichen.

Die disambiguieren zu dem template Schlüsselwort wird, bevor entweder variable oder constant erforderlich. Fall 1:

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

Fall 2:

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

Es Art wäre schön, wenn das Schlüsselwort nur in tatsächlichen mehrdeutigen Situationen erforderlich war (die Art selten sind), aber es macht den Parser viel einfacher zu schreiben und verhindert, dass solche Probleme Sie überraschen.

Für standardese siehe 14.2/4:

Wenn der Name einer Vorlage Spezialisierung Mitglied erscheint nach. oder -> in einem Postfix-Ausdruck oder nach verschachteltem-name-Spezifizierer in einem qualifizierte-ID und den Postfix-Ausdruck oder qualifizierte Nummer hängt explizit auf einem Template-Parametern (14.6.2), Der Mitgliedsschablonename muss mit der Schlüsselwortvorlage vorangestellt werden. Andernfalls wird angenommen, dass der Name einen Nicht-Template-Namen enthält.

+0

+1 für das erste Beispiel: Das ist ein wirklich toller Codeausschnitt, um die Kontextsensitivität der C++ - Grammatik zu demonstrieren und warum diese Schlüsselwörter benötigt werden. –

0

Das erste Beispiel kompiliert und läuft für mich in VS Fein 2010

7

Abschnitt 5.1 von C++ Templates erklärt dieses Konstrukt im Detail

Die unten Funktion hat ein Problem

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

} 

hier T = char und U = int

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

ist bei ng angerufen. Doch eine solche Funktion nicht vorhanden

Auch wenn unter normalen Umständen ‚char‘ ist umwandelbar ‚int‘, das nicht gut halten für explizit angegebenen Vorlage Argumente

Verwandte Themen