我认为模板的定义是错误的,在这两种情况下你都会触发精确递归。我原以为编译器会在编译器内部出现一些 stackoverflow 而死,但会产生不同的错误......
are_same
可变参数模板的实现可以是:
template <class... Args> // base (optional to declare the template)
struct are_same;
template <class A, class B, class... Args> // recursion
struct are_same<A,B,Args...> {
static const bool value = is_same<A,B>::value && are_same<A,Args...>::value;
};
template <class A, class B> // stop condition
struct are_same<A,B> {
static const bool value = is_same<A,B>::value;
};
请注意,在该recursion
步骤中,从参数列表中删除了一个参数,因此要解决的新问题是原始问题的简化版本。这种类型的模板元编程与递归非常相关,并且适用相同的规则,为了能够使用递归,您需要确保每个递归步骤都能让您更接近解决方案。在这种特殊情况下,给定 N 个可能相同类型的列表,每一步都将问题简化为查找 N-1 个类型是否相同。
您也可以使用问题的退化版本作为停止条件(替换前一个)are_same
:
template <class A>
struct are_same<A> {
static const bool value = true;
};
从某种意义上说,这是退化的,询问单个类型是否 *are_same* 并没有真正意义,但对于不同的元编程任务,它可能是合适的。
不依赖于的另一种可能更有效的算法(我不确定编译器是否会避免在上面的递归步骤中实例化模板)is_same
可能是:
template <class... Args>
struct are_same;
template <class A, class... Args>
struct are_same<A,A,Args...> { // recursion
static const bool value = are_same<A,Args...>::value;
};
template <class A, class B, class... Args>
struct are_same<A,B,Args...> { // cut, A and B are not the same
static const bool value = false;
};
template <class A>
struct are_same<A> { // end of recursion
static const bool value = true;
};
在这种情况下,只要两种类型相同,编译器就会优先选择recursion
步骤cut
,因此我们不需要is_same
内部检查。同时,如果编译器进入该cut
步骤,我们不需要处理类型列表的其余部分,因为我们已经知道了答案。