阅读了很多关于模板,模板专业化和部分专业化的文章后,我仍然无法理解以下模板巫术的工作方式和原因。
template <class T> class Signal;
template <class Arg, class Ret>
class Signal<Ret (Arg)> {
typedef std::function<Ret (Arg)> Callback;
};
int main() {
Signal<void (int x)> signal;
}
我很清楚代码的作用以及如何利用它,我只是无法理解为什么以及如何使用它。编译器如何解释包含空格和括号的特化参数,例如class Signal<Ret (Arg)>
? void (int x)
如何/为何匹配专业化class Signal<Ret (Arg)>
?为什么template <class Arg, class Ret>
甚至是必要的?为什么不在“普通”专业化中使用<>
? class Arg
和class Ret
的顺序似乎不重要,为什么?
如果这些问题没有任何意义,我很抱歉。如果他们不这样做,请不要直接回答他们。我只想了解上述代码的工作原理和原因。感谢。
答案 0 :(得分:2)
具有单个模板参数的模板的定义:
template <class T> class Signal;
使用具有返回值(或void)和参数的函数来专门化模板:
template <class R, class A>
class Signal<R (A)> {
typedef std::function<R (A)> Callback;
};
使用具有返回值(或void)和两个参数的函数来专门化模板:
template <class R, class A0, class A1>
class Signal<R (A0, A1)> {
typedef std::function<R (A0, A1)> Callback;
};
等等......
即使每个专业化都是具有多个参数的模板,它指的是函数签名的单个模式。 “普通”专业化不能描述一组功能签名,而只能描述一个:
template <>
class Signal<void (int)> {
typedef std::function<void (int)> Callback;
};
注意:只有专业化中模板参数的顺序(例如:信号&lt; R(A)&gt;)是相关的。
答案 1 :(得分:2)
问题是void(int x)
是单一类型,即采用int
并返回void
的函数类型(此处忽略参数名x
)类型绑定到T
中的Signal
。但是这种情况有一个专门化,所以它被选中,Ret
被绑定到void
和Arg
到int
。顺序与模板aragument list 中的无关,但无论你在专门的参数中使用它们的位置都很重要,因为传递的参数将被绑定到不同的方式。
对于数组类型也是如此:
template <typename T>
struct C;
template <typename Element, std::size_t size>
struct C<Еlement[size]> {};
int main() {
C<int[42]> c;
}
您所谓的“正常”专业化实际上名为完全专业化,因为它们不需要提供其他参数来形成类型,因此空模板参数名单。您的示例和上面的示例称为部分特化,也可以用于其他模板:
template <typename T, int size>
struct Array {};
template <typename Element, std::size_t size>
struct C<Array<Еlement, size>> {};
int demo() {
C<Array<int, 10>> a;
}