0

This question is a follow-up of another question.
Consider the following code:

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(void)> s; // (1)
    Alias<void> alias; // (2)
}

If we comment out (2), the example complies, otherwise the compilation fails.
From the linked question we find that (2) fails because:

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 typecv void.

Moreover:

[ 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 ]

What's not clear to me is why (1) compiles.

In other terms, if (2) fails because Args is a dependent type and suffers from the above mentioned limitation in:

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

The same problem should affect Args in:

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

Why is it fine using void as S<void(void)> in this case?
Note that the rush is towards the std::function that accepts as well this kind of signature.

Community
  • 1
  • 1
skypjack
  • 49,335
  • 19
  • 95
  • 187
  • 2
    `S` is equivalent to `S` and deduces `Args` to be an empty pack. That is to say, the *type-id*s `void(void)` and `void()` name the exact same type. – T.C. Mar 09 '16 at 07:15
  • That what I guessed, but the alias and the structure should behave almost the same, because `Alias` ends with `S`. Right? – skypjack Mar 09 '16 at 07:16
  • No, because `Args` in `Alias` is dependent. – T.C. Mar 09 '16 at 07:18
  • @T.C. Also `Args` in `template struct S { };` is dependent, am I wrong? It's a template parameter, but I'm not sure if those parameters must be considered dependent types when dealing with specializations. – skypjack Mar 09 '16 at 08:12
  • `Args` in `S` is deduced, not specified, and it's deduced against `void()`, which is the function type that the *type-id* `void(void)` names. – T.C. Mar 09 '16 at 09:23
  • @T.C. Ok, got the reason behind that now, it's due to the fact that it is deduced because of part of a specialization. If you put the comment in an answer, I'll accept it to close the question. – skypjack Mar 09 '16 at 09:27

0 Answers0