sfinae 和自定义幂函数的编译器错误

Compiler error with sfinae and custom power function

我想用像 sfinae 这样的元编程方式实现整数的力量

#include <iostream>

template<bool B, typename T = void> struct enable_if;

template<typename T>
struct enable_if<true, T> { using type = T; };

template<typename T>
struct enable_if<false, T> {};

template<int N, typename T>
typename enable_if <(N == 0), T>::type my_pow(T x) {
    return 1;
};

template<int N, typename T> // block1
typename enable_if <(N > 0) && (N % 2 == 1), T>::type my_pow(T x) {
    return my_pow<N - 1>(x) * x;
};

template<int N, typename T> // block2
typename enable_if <(N > 0) && (N % 2 == 0), T>::type my_pow(T x) {
    T p = my_pow<N / 2>(x);
    return p * p;
};

};

auto y_2_5 = my_pow<2>(5);
//auto y_3_5 = my_pow<3>(5);

int main()
{
    std::cout << y_2_5 << std::endl;
//    std::cout << y_3_5 << std::endl;
}

它适用于 y_2_5,但如果取消注释 y_3_5 行则不起作用。但是如果你交换 block1 和 block2,y_2_5 也不起作用。 也许,这是由于某些编译器的标志而发生的。有可能修复它吗?

声明的顺序很重要。无论哪个块先出现,都看不到另一个块。这意味着当您在第一个块的主体中​​进行重载决策时,第二个块将不会成为候选者。只有到那时可见的声明才是候选者(不包括其他细节,如 ADL,此处不适用)。

补救措施非常简单,在定义它们之前添加两个函数模板的声明。这样,实际上先定义哪个并不重要。

template<int N, typename T>
typename enable_if <(N > 0) && (N % 2 == 1), T>::type my_pow(T x);

template<int N, typename T>
typename enable_if <(N > 0) && (N % 2 == 0), T>::type my_pow(T x);

template<int N, typename T> // block1
typename enable_if <(N > 0) && (N % 2 == 1), T>::type my_pow(T x) {
    return my_pow<N - 1>(x) * x;
}

template<int N, typename T> // block2
typename enable_if <(N > 0) && (N % 2 == 0), T>::type my_pow(T x) {
    T p = my_pow<N / 2>(x);
    return p * p;
}