我有一段代码(这是从较大的项目中复制出来的最小代码)。
#include <type_traits>
template<typename PA, typename E = void>
struct poly_gcd_reduce_helper;
template<typename PA>
struct poly_gcd_reduce_helper<PA, typename std::enable_if<(PA::sign() > 0)>::type>
{
static constexpr auto val = PA{};
};
template<typename PA>
struct poly_gcd_reduce_helper<PA, typename std::enable_if<(PA::sign() <= 0)>::type>
{
static constexpr auto val = -PA{};
};
template<typename PA, typename PB>
struct poly_gcd
{
static constexpr auto val = poly_gcd<PB, decltype(PA{} -(PA{} / PB{}) * PB {})>::val;
};
template<typename PA>
struct poly_gcd<PA, typename PA::zero_type>
{
static constexpr auto val = poly_gcd_reduce_helper<PA>::val;
};
template<int p>
struct myint{
static constexpr int val = p;
using zero_type = myint<0>;
constexpr int sign() const {
if constexpr (p > 0)
return 1;
else if constexpr (p == 0)
return 0;
else
return -1;
}
constexpr auto operator-() const {
return myint<-p>{};
}
};
template<int a, int b>
static constexpr auto operator/(myint<a> aa, myint<b> bb)
{
return myint<a / b>{};
}
template<int a, int b>
static constexpr auto operator*(myint<a> aa, myint<b> bb)
{
return myint<a * b>{};
}
template<int a, int b>
static constexpr auto operator-(myint<a> aa, myint<b> bb)
{
return myint<a - b>{};
}
template<int a, int b>
static constexpr auto operator+(myint<a> aa, myint<b> bb)
{
return myint<a + b>{};
}
int main() {
constexpr auto zou = poly_gcd<myint<2>, myint<4>>::val;
}
它在gcc 9.2中失败,并出现以下错误:
在'constexpr const auto poly_gcd,myint <0 >> ::: val的实例中:从'constexpr const auto poly_gcd,myint <2>> :: val'递归地需要需要'constexpr const auto poly_gcd,myint <4>> :: val':70:56:从这里需要:27:27:错误:类型不完整嵌套名称说明符中使用的'poly_gcd_reduce_helper,void>'
静态constexpr自动val = poly_gcd_reduce_helper :: val;
显然,编译器试图实例化poly_gcd_reduce_helper,void>,即使我根据第一个模板参数的符号具有poly_gcd_reduce_helper的互斥实现。
我必须承认,我现在不知道该怎么办。
在poly_gcd_reduce_helper
的专业化中,给定用法PA::sign() > 0
,sign()
应该是静态成员函数;而myint::sign()
是非静态成员函数。然后对于myint
,就永远不会选择poly_gcd_reduce_helper
的专业化。
更改为
static constexpr int sign() {
if constexpr (p > 0)
return 1;
else if constexpr (p == 0)
return 0;
else
return -1;
}
不需要将整数包装为特殊类型,这可以大大简化:
#include <iostream>
#include <type_traits>
using namespace std;
template<int V, typename E=void>
struct poly_gcd_reduce_helper;
template<int V>
struct poly_gcd_reduce_helper<V, typename std::enable_if<(V > 0)>::type> {
static constexpr auto val = +V;
};
template<int V>
struct poly_gcd_reduce_helper<V, typename std::enable_if<(V <= 0)>::type> {
static constexpr auto val = -V;
};
template<int VA, int VB>
struct poly_gcd {
static constexpr auto val = poly_gcd<VB, VA-(VA/VB)*VB>::val;
};
template<int VA>
struct poly_gcd<VA, 0> {
static constexpr auto val = poly_gcd_reduce_helper<VA>::val;
};
int main() {
constexpr auto zou = poly_gcd<2,4>::val;
cout << "zou: " << zou << endl;
}
╰─▸./test邹:2