2016-03-08 10 views
10

Rozważmy następujący kod:Alias ​​szablon, częściowa specjalizacja i nieprawidłowy typ parametru 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; 
} 

To działa dobrze, jak oczekiwano, a zarówno linię udziałem S i jeden z udziałem Alias zdefiniować pod maską tego samego typu S<void(int)>.

Teraz rozważyć następujące zmiany:

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

spodziewałem się, że kompilacja z powodów, które są podobne do tych wymienionych powyżej.
Jest rzeczą oczywistą, że nie skompilować ze względu na linii z udziałem Alias, zamiast tego pojawia się błąd:

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

[...]

error: invalid parameter type 'void'

pytanie jest dość prosta: co brakowało mi tutaj?

Odpowiedz

5

Z [dcl.fct] nacisk kopalni:

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 .

W tym przypadku Args... jest zależny od typu pakietu, tak void nie jest dozwolone. Pomysł ten jest powtarzany w notatce w [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 ]

Zauważ, że S<void(void)> kompiluje od void(void) nie jest zależny i jest odpowiednikiem void(), więc Ret(Args...) nigdy nie jest wywnioskować mieć void na liście parametrów - zostało wydedukowane z pustym Args....


Przynajmniej istnieje proste rozwiązanie, w którym można po prostu napisać Alias<>.

+0

Sposób obejścia tego problemu jest oczywisty, ale czy nie powinien on kompilować obu linii z tego samego powodu? Również 'S ' prowadzi do dedukcji, która próbuje (dobrze, powodzeniem) stworzyć * typ funkcji, w której parametr ma typ 'void' *. Czy się mylę? – skypjack

+0

@skypjack Właśnie znalazłem sekcję, której szukałem. 'Void' musi być niezależny. – Barry

+0

Dziękujemy za referencje. W każdym razie, nie jest również 'Args' w' szablon struct S {}; 'typ zależny, który powinien cierpieć na ten sam problem? – skypjack

Powiązane problemy