Reputation: 33599
I don't understand why this doesn't compile, can you give me a brief rationale?
template <typename... Args>
class Signal{};
template <template <typename... SignalArgs> class Signal, typename... Args>
void f(Signal<SignalArgs...>&& signal, Args&&... args)
{}
The error gcc provides is:
error: 'SignalArgs' was not declared in this scope; did you mean 'Signal'?
11 | void f(Signal<SignalArgs...>&& signal, Args&&... args)
| ^~~~~~~~~~
| Signal
<source>:11:25: error: expected parameter pack before '...'
11 | void f(Signal<SignalArgs...>&& signal, Args&&... args)
| ^~~
<source>:11:28: error: template argument 1 is invalid
11 | void f(Signal<SignalArgs...>&& signal, Args&&... args)
|
And more importantly, what is a proper way to write such an overload? Do note that I need two variants of f
- the one in question, and the other is template <typename F> void f(F&&);
I definitely don't want any instances of Signal
, including Signal<>
, going into the generic overload.
Try it online on Godbolt: https://godbolt.org/z/Xawz6G
Upvotes: 0
Views: 85
Reputation: 15941
The problem is that SignalArgs
does not declare a parameter of your function template. It's simply an identifier that may optionally occur in the declarator that declares your actual template parameter, which is Signal
. It's basically the same thing as with names of function parameters in a declarator that declares a function type, e.g.:
void f(void(*fp)(int a, int b))
{}
Here, f
is a function that takes a parameter fp
that is a pointer to a function that takes two parameters of type int
. The identifiers a
and b
are redundant in the same way that SignalArgs
is in your original example. They may appear, but they don't really serve any purpose.
Since SignalArgs
is not a template parameter of your function template, there's no way it could be deduced (template argument deduction only concerns itself with deducing arguments for the parameters of a function template). The way to do what you want is to introduce a separate template parameter that is used in the type of your function parameter signal
in such a way that it can be deduced:
template <template <typename...> class Signal, typename... SignalArgs, typename... Args>
void f(Signal<SignalArgs...>&& signal, Args&&... args)
{}
working example here
Upvotes: 2