2016-03-08 6 views
10

den folgenden Code vor:Alias-Vorlage, partielle Spezialisierung und der ungültige Parameter Typ void

template<typename F> 
struct S; 

template<typename Ret, typename... Args> 
struct S<Ret(Args...)> { }; 

template<typename... Args> 
using Alias = S<void(Args...)>; 

int main() { 
    S<void(int)> s; 
    Alias<int> alias; 
} 

Es funktioniert gut, wie erwartet, und sowohl die Linie anzupassen S und die eine Beteiligung Alias unter der Haube definieren die gleiche Art S<void(int)>. Jetzt

, die folgenden Änderungen:

int main() { 
    S<void(void)> s; // this line compiles 
    Alias<void> alias; // this line does not 
} 

ich erwartet, dass es aus Gründen, zu kompilieren, die die denen ähnlich sind oben erwähnt.
Es versteht sich, dass es wegen der Zeile nicht kompilieren Alias beteiligt, stattdessen erhalte ich die Fehlermeldung:

In substitution of 'template using Alias = S [with Args = {void}]'

[...]

error: invalid parameter type 'void'

Die Frage ist ziemlich einfach: was ich hier verpasst?

Antwort

5

Von [dcl.fct], Hervorhebung von mir:

A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list. Except for this special case, a parameter shall not have type cvvoid .

In diesem Fall Args... ist ein abhängiges Typ-Pack, so void es nicht erlaubt ist. Diese Idee wird in einer Notiz wiederholt in [temp.deduct]:

[ Note: Type deduction may fail for the following reasons:
— [...]
— Attempting to create a function type in which a parameter has a type of void , or in which the return type is a function type or array type.
— [...]
—end note ]

Beachten Sie, dass S<void(void)> kompiliert seit void(void) nicht-abhängig und entspricht void(), so Ret(Args...) wird nie void in der Parameterliste haben, abgeleitet - es ist mit Args... leer abgeleitet.


Immerhin gibt es eine einfache Abhilfe, dass Sie nur Alias<> schreiben kann.

+0

Die Problemumgehung ist offensichtlich, aber sollte es nicht fehlschlagen, die beiden Zeilen aus dem gleichen Grund zu kompilieren? Auch 'S ' führt zu einem Abzug, der (gut, Erfolg) versucht, um * einen Funktionstyp zu erzeugen, in dem ein Parameter eine Art 'void' * hat. Liege ich falsch? – skypjack

+0

@skypjack Habe gerade den Abschnitt gefunden, nach dem ich gesucht habe. Die "Leere" muss unabhängig sein. – Barry

+0

Vielen Dank für die Referenz. Wie auch immer, ist nicht auch 'Args' in' Template Struktur S {}; 'ein abhängiger Typ, der unter dem gleichen Problem leiden sollte? – skypjack