我想用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的comment,则无效。但是如果你把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;
}