2016-01-22 4 views
22

Ich bekomme nicht den Grund, für den ein Parameter-Pack am Ende der Parameterliste sein muss, wenn letzterer an eine Klasse gebunden ist, während die Einschränkung gelockert wird, wenn die Parameterliste Teil einer Member-Methodendeklaration ist.Parametersatz muss am Ende der Parameterliste stehen ... Wann und warum?

Mit anderen Worten, dieser kompiliert:

class C { 
    template<typename T, typename... Args, typename S> 
    void fn() { } 
}; 

Hier finden Sie eines nicht:

template<typename T, typename... Args, typename S> 
class C { }; 

Warum der erste Fall ist richtig betrachtet und die zweite ist nicht wahr?
Ich meine, wenn es legale Syntax ist, sollte es nicht in beiden Fällen sein?

Um klar zu sein, das eigentliche Problem ist, dass ich eine Klasse ähnelt dem folgenden wurde die Definition:

template<typename T, typename... Args, typename Allocator> 
class C { }; 

die allocator Typ als der letzte Typ Having würde geschätzt, aber ich kann irgendwie drum herum arbeiten (Wie auch immer, wenn Sie einen Vorschlag haben, ist es geschätzt, vielleicht sind Ihre viel eleganter als meins !!).
Das heißt, habe ich den Fehler:

parameter pack 'Args' must be at the end of the template parameter list

Also, ich war nur neugierig, um zu verstehen, warum es in einigen Fällen akzeptiert wird, aber es ist nicht in einigen anderen.

Here ist eine ähnliche Frage, aber es erklärt einfach, wie man das Problem löst, und das war mir ziemlich klar.

+0

Sie verwenden einen Standard für den letzten Typparameter - soweit ich mich erinnere, ändert sich die Sache sehr. (Aber ich vergesse die Details). Vielleicht sollten Sie die Standardeinstellungen in Ihren beiden Eröffnungsbeispielen angeben? –

+0

Können Sie ein Beispiel geben, wie Sie diese Vorlagen aufrufen möchten? Ich bin nicht sicher, dass es sehr relevant ist, aber es könnte helfen –

+0

Sorry, der Standardparameter war ein Fehler, nicht mehr da. Ich plane, diese Vorlage wie jede andere zu verwenden: 'C >'. Das Problem liegt in der Tatsache, dass diese Syntax für eine Member-Methode richtig ist, aber es ist nicht für eine Klassendefinition und ich verstehe nicht, warum es nicht ist !! – skypjack

Antwort

16

Es ist für Funktionsschablonen gültig, aber nur dann, wenn Argument Abzug der Compiler die Template-Parameter lösen helfen können, wie es beispielsweise Ihre Funktion Vorlage steht, ist praktisch nutzlos, weil

template<typename T, typename... Args, typename S> void fn() { } 
int main() { fn<int, int, int>(); } 
test.cpp: In function 'int main()': 
test.cpp:2:32: error: no matching function for call to 'fn()' 
int main() { fn<int, int, int>(); } 
           ^
test.cpp:1:57: note: candidate: template<class T, class ... Args, class S> void fn() 
template<typename T, typename... Args, typename S> void fn() { } 
                 ^
test.cpp:1:57: note: template argument deduction/substitution failed: 
test.cpp:2:32: note: couldn't deduce template parameter 'S' 
int main() { fn<int, int, int>(); } 

der Compiler hat Es gibt keine Möglichkeit zu bestimmen, welche Template-Parameter zu dem Parameterpack gehören und welche zu S. In der Tat als @ T.C. weist darauf hin, dass es eigentlich ein Syntaxfehler sein sollte, da eine auf diese Weise definierte Funktionsvorlage niemals instanziiert werden kann.

Eine nützliche Funktion Vorlage würde, wie jetzt so etwas wie

template<typename T, typename... Args, typename S> void fn(S s) { } 

sein kann der Compiler den Funktionsparameter s mit dem Vorlagentyp S, mit dem Nebeneffekt, dass S wird immer eindeutig entsprechen sein abgeleitet - alle expliziten Template-Parameter nach dem ersten werden zu Args gehören.

Nichts davon arbeitet für (primär) Klassen-Templates werden die Parameter nicht abgeleitet und es ist ausdrücklich verboten:

Von Entwurf n4567

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf

[temp.param]/11

(wenn sie abgeleitet wurden, wäre es mehrdeutig wie im Beispiel der Funktionsvorlage).

+0

Uhm, OK, es scheint, dass das Beispiel in der Frage zu sehr reduziert wurde, aber guter Punkt, um darauf hinzuweisen, wie man es machen kann oder nicht. Also ist es legale Syntax und es geht nur um Deduktion, keine Möglichkeit, eine Klasse wie die in der Frage zu definieren, ich muss eine vernünftige und brauchbare Lösung finden ... Irgendeine Idee? Es wäre wünschenswert, wie in der Frage erwähnt. :-) – skypjack

+0

@skypjack Ich denke, du müsstest erklären, was genau du zuerst machen willst, zum Beispiel warum 'Allocator' am Ende sein muss. – user657267

+0

Dafür gibt es in fast allen Klassen der Bibliothek, an denen ich arbeite, aber das ist das erste Mal, dass ich ein Parameterpack in der Klassendefinition haben muss. Ganz einfach, aber wenn ich noch keine Lösung finden kann, kann ich sie natürlich in eine andere Position bringen. – skypjack

11

Der erste ist nicht richtig. Der Compiler ist einfach fehlerhaft und konnte nicht diagnostiziert werden. [temp.param]/11:

A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list of the function template or has a default argument (14.8.2).


Wenn die Funktion Typ T(Args...) zum Endanwender sinnvoll ist, eine Möglichkeit, dieses Problem zu beheben wäre stattdessen eine partielle Spezialisierung zu verwenden:

template<class F, class Alloc> class C; //undefined 
template<class T, class... Args, class Alloc> 
class C<T(Args...), Alloc> { 
    // implementation 
}; 

auf dem tatsächlichen Je Anforderungen, Typ-Löschen des Allokators könnte auch eine Überlegung wert sein.

+2

Der Compiler ist GCC5, sollte ich ein Ticket auf ihrem Bug-Tracking-System öffnen, wenn für dieses Problem keine existiert? – skypjack

+0

Was meinst du mit * Löschen des Allokators *? Ich kenne die Art des Löschens als ein Idiom, aber ich verstehe nicht, worauf Sie sich beziehen. – skypjack

+1

@skypjack Grundsätzlich, was "std :: function", "std :: promise" und "std :: packaged_task" tun. Sie nehmen einen Zuordner in einem Konstruktor und geben Sie ihn löschen, so dass Ihr Typ nicht vom Typ des Zuordners abhängt. –

Verwandte Themen