У меня есть этот кусок кода (минимальный, воспроизведенный из более крупного проекта).
#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;
}
Ошибка при g cc 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>', используемый в описателе вложенного имени
stati c constexpr auto val = poly_gcd_reduce_helper :: val;
Очевидно, компилятор пытается создать экземпляр poly_gcd_reduce_helper, void>, даже если у меня есть взаимоисключающие реализации poly_gcd_reduce_helper в зависимости от знака первого аргумента шаблона.
Должен признать, я не знаю, что делать сейчас.