解构表达式

Deconstructing the expression

参照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
}

我正在尝试阅读这个重载决议,假设我是偶数,并遵守运算符优先规则:

deconstruct 1: template<int I> div(char (*) [1] = 0) //since I % 2 == 0

那么上面的读法是否正确:

模板函数div需要一个函数指针参数,其签名为char (*) [int I = 1],默认为0或NULL?

感谢您的想法。

如果我们像 div<21> 那样调用它,编译器会尝试将 I = 21 替换到模板中。我们得到:(__div21是代入后的假想函数名)

void __div21(char(*)[0] = 0) {
    // this overload is selected when I is even
}
void __div21(char(*)[1] = 0) {
    // this overload is selected when I is odd
}

长度为零的数组是ill-formed,所以第一个版本是替换失败。它已从重载决议中删除。第二个版本没问题,所以它参与了重载决议。因此,div<21> 调用第二个重载。


如果我们像 div<42> 那样调用它,编译器会尝试将 I = 42 替换到模板中。我们得到:(__div42是代入后的假想函数名)

void __div42(char(*)[1] = 0) {
    // this overload is selected when I is even
}
void __div42(char(*)[0] = 0) {
    // this overload is selected when I is odd
}

零长度数组是ill-formed,所以第二个版本是替换失败。它已从重载决议中删除。第一个版本没问题,所以它参与了重载决议。因此,div<42> 调用第一个重载。


从 C++17 开始,我们可以使用 if constexpr 结构使代码更容易理解:

template <int I>
void div()
{
    if constexpr (I % 2 == 0)
        /* handle even case */;
    else
        /* handle odd case */;
}