我不明白为什么它不能编译,您能给我一个简单的理由吗?
template <typename... Args>
class Signal{};
template <template <typename... SignalArgs> class Signal, typename... Args>
void f(Signal<SignalArgs...>&& signal, Args&&... args)
{}
gcc提供的错误是:
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)
|
更重要的是,编写这种重载的正确方法是什么?请注意,我需要两个f
的变体-一个在讨论中,另一个是template <typename F> void f(F&&);
我绝对不希望任何Signal
的实例,包括Signal<>
,进入通用过载。
在Godbolt上在线尝试:https://godbolt.org/z/Xawz6G
答案 0 :(得分:2)
问题是SignalArgs
没有声明函数模板的参数。它只是一个标识符,可以有选择地出现在declarator中,该标识符声明您的实际模板参数,即Signal
。基本上与声明函数类型的声明器中函数参数的名称相同:
void f(void(*fp)(int a, int b))
{}
在这里,f
是一个带有参数fp
的函数,该参数是一个指向带有两个int
类型的参数的函数的指针。标识符a
和b
是冗余的,与原始示例中的SignalArgs
相同。它们可能会出现,但实际上并没有任何作用。
由于SignalArgs
不是函数模板的模板参数,因此无法推论(模板参数推论仅涉及推导函数模板参数的论点本身)。执行所需操作的方法是引入一个单独的模板参数,该模板参数以可以推论的方式在函数参数signal
的类型中使用:
template <template <typename...> class Signal, typename... SignalArgs, typename... Args>
void f(Signal<SignalArgs...>&& signal, Args&&... args)
{}
工作示例here