Es muss separate template
Klauseln für jede Vorlage, die beteiligt ist. Hier sind zwei Vorlagen beteiligt sind, dass alle verdienen ihre (nicht leer) Template-Klauseln:
- Die Klassenvorlage
Foo
- Der Konstruktor Vorlage
diesen Fall betrachtet, die wegen der Mehrdeutigkeit versagt , wo der Parameter U
zu
gehört jetzt
template<typename T>
struct A {
template<typename U> void f();
};
template<typename T, typename U>
void A<T>::f() { }
, was ist mit dem Parameter U
up? Sicher, der Compiler könnte erraten, dass es zu f
gehören könnte, aber Ratespiel ist nicht das, was der Compiler gefällt :) Die vorhandene Regel besagt, dass Template-Klauseln in der richtigen Reihenfolge angezeigt werden, abhängig von der Verschachtelung von Vorlagen. Alles ist dann klar.
Selbst wenn man mit einer Regel aufkommt, wie man die Parameter mit Argumenten der beteiligten Templates vergleicht (bisher sehe ich keine wirkliche Schwierigkeit darin), wäre das inkonsistent. Denn ab sofort listet eine Template-Klausel alle Parameter auf, die die entsprechende Vorlage akzeptiert. Ähnlich wie eine Funktionsparameterliste. Wenn wir alles in einer Klausel, dass klare semantische gebrochen werden konnte setzen würde - nicht zu erwähnen, dass, wenn wir wieder die Definition in die Klasse setzen, ganz plötzlich der Vorlage würde eine eigene Klausel erhalten:
// provides arguments for A's parameters, then for f ones
// when it's called
A<int> a;
a.f<bool>();
Es ist viel natürlicher, wenn wir separate Template-Klauseln haben, die jeweils ihre eigenen Argumente erfassen.So ist die Syntax für die oben falsche Definition
template<typename T>
template<typename U>
void A<T>::f() { }
nun auch die Leser des Codes sofort sieht, dass dies eine Definition eines Mitglieds Vorlage, und kein (Potential versehentlich deklariert, aber nicht verwendet) zweiter Parameter für A
.
Dies ist * nicht * ein Kopierkonstruktor. Der Compiler wird sich beschweren, wenn Sie versuchen, die Klasse 'Foo' nach Wert zu übergeben. –