在有关SFINAE的cppreference文章中,我遇到了我不理解的这种语法:
template <int I> void div(char(*)[I % 2 == 0] = 0) {
// this overload is selected when I is even
}
template <int I> void div(char(*)[I % 2 == 1] = 0) {
// this overload is selected when I is odd
}
我知道它是一个模板函数声明,但是我不明白参数的含义。特别是char(*)[I % 2 == 0] = 0
中的方括号是什么,为什么它等于0?
答案 0 :(得分:6)
在C ++中,大小为0的数组是非法的,因此根据I
的值选择特定的重载:当I
为5时,char(*)[I % 2 == 0]
将是一个指向数组的指针。大小false
,即零,而另一个数组指针完全合法。
= 0
只是默认的忽略参数值,可避免您每次调用此函数时键入(0)
。
在C ++ 20中,它将更加明显和直接:
template<int I> requires (I % 2 == 0) void div() {
}
甚至在C ++ 17中:
template<int I> void div() {
if constexpr(I % 2 == 0) {
}
else {
}
}
答案 1 :(得分:1)
当I
达到偶数时(记住false
转换为0
,true
转换为1
):
template <int I> void div(char(*)[1] = 0) {
// this overload is selected when I is even
}
template <int I> void div(char(*)[0] = 0) {
// this overload is selected when I is odd
}
第二次尝试使用大小为0
并根据该page上的项目符号点的数组:
以下类型错误是SFINAE错误:
试图创建一个空数组,引用数组,函数数组,数组 负数,非整数大小的数组,或零大小的数组。
...触发SFINAE,并选择第一个过载。当0
为奇数时,第一个重载的数组大小为I
。请注意,该参数未命名。它不在函数内部使用,其唯一目的是触发SFINAE。调用此函数不需要传递参数,因为它具有默认值,即=0
。传递参数将毫无用处,因为无论如何都不会使用其值。
这是SFINAE的相当神秘的示例。从C ++ 11开始,您可能将std::enable_if
与template <int I> is_odd;
或类似名称一起使用,并且从C ++ 20开始,您将使用概念。