嵌套名称说明符中使用std enable_if使用的不完整类型

问题描述 投票:2回答:2

我有一段代码(这是从较大的项目中复制出来的最小代码)。

#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的互斥实现。

我必须承认,我现在不知道该怎么办。

c++ templates c++17 typetraits
2个回答
3
投票

poly_gcd_reduce_helper的专业化中,给定用法PA::sign() > 0sign()应该是静态成员函数;而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;
}

LIVE


0
投票

不需要将整数包装为特殊类型,这可以大大简化:

#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

© www.soinside.com 2019 - 2024. All rights reserved.