奇怪的SFINAE代码

时间:2016-06-05 03:34:06

标签: c++ sfinae

我发现这段代码与SFINAE结合在一起:

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
}

它是如何工作的?它看起来像一个未命名的参数数组,但我不明白下标如何帮助解决重载问题。

3 个答案:

答案 0 :(得分:7)

C ++中的数组边界不能为零。如果表达式(例如I % 2 == 0)为false,则转换为零,从而导致类型无效,从而导致替换失败。

基本上,它是std::enable_if的混淆版本。

答案 1 :(得分:1)

请记住这是这样称呼的:div<1234>() =&gt;调用第一个重载。

要理解你只需要查看参数:

char(*)[I % 2 == 0] = 0 这意味着它是指向字符数组的指针。此数组的默认值为0.这意味着您还可以执行char a[] = "hello world"; div<1234>(a);

I % 2 == 0在编译时进行评估。你应该知道它的作用。即使是整数也是如此,奇数整数使得这个错误。 True计算结果为1,false计算结果为0.但是没有像零元素那样的数组。这就是你所说的SFINAE错误。这并不意味着它是一个根本性的错误,只是模板中的空白无法被充分替代。 模板不匹配

答案 2 :(得分:0)

如T.C.所述。因为你不能拥有0元素的数组,当条件为假时,布尔值false被转换为0:类型变为char(*)[0](指向大小为0的char数组的指针)并触发SFINAE。

现在,以更传统(可读)的方式,您通常会让std::enable_if完成这项工作:

template <int I, std::enable_if_t<I%2>* = nullptr>
div() {
    std::cout << "I (" << I <<") am odd." << std::endl;
}

template <int I, std::enable_if_t<!(I%2)>* = nullptr>
div() {
    std::cout << "I (" << I <<") am even." << std::endl;
}

正如Coliru所示。