使用sfinae和自定义电源函数时出现编译器错误

问题描述 投票:0回答:1

我想用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也不工作了。有没有可能解决这个问题?

c++ metaprogramming
1个回答
3
投票

声明的顺序很重要。无论哪个代码块先出现,都不会看到其他代码块。这意味着,当你在第一个块的主体中进行重载解析时,第二个块将不会成为候选者。只有在这之前可见的声明才是候选者(不包括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;
}
© www.soinside.com 2019 - 2024. All rights reserved.