c++ friend operator template specialization

亡梦爱人 提交于 2021-02-07 09:37:34

问题


I have a generalized modulo struct called quotient_ring. The relevant bits are shown below.

template <typename R = long long>
struct quotient_ring{
    using Q = quotient_ring;
    R x, m;

    ...

    template <typename T>
    friend constexpr std::basic_ostream<T> &operator<< (std::basic_ostream<T> &str, const Q &q){
        return str << '(' << q.x << ")%(" << q.m << ')';
    }
};

This operator << would print something like 2 mod 7 as (2)%(7). The reason I need the brackets is because the type R can become very nested. However, if R is only an arithmetic type, such as long long, I would like to print without the brackets. I found that one way to accomplish this is as follows.

template <typename T>
friend constexpr std::basic_ostream<T> &operator<< (std::basic_ostream<T> &str, const Q &q){
    if constexpr (std::is_arithmetic<R>::value) return str << q.x << '%' << q.m;
    else return str << '(' << q.x << ")%(" << q.m << ')';
}

I think this is a fine solution. However, I would like to know if the same can be achieved by means of template specialization. I tend to personally like template specialization more than branching on type traits.


回答1:


I tend to personally like template specialization more than branching on type traits.

Why? if constexpr is a compile-time branch. The equivalent SFINAE is far less readable.

template <typename R = long long>
struct quotient_ring{
    using Q = quotient_ring;
    R x, m;

    template <typename Char>
    friend constexpr std::enable_if_t<
        std::is_arithmetic_v<R>,
        std::basic_ostream<Char> &
    >
    operator<< (std::basic_ostream<Char> &str, const Q &q){
        return str << q.x << '%' << q.m;;
    }

    template <typename Char>
    friend constexpr std::enable_if_t<
        !std::is_arithmetic_v<R>,
        std::basic_ostream<Char> &
    >
    operator<< (std::basic_ostream<Char> &str, const Q &q){
        return str << '(' << q.x << ")%(" << q.m << ')';
    }
};

int main() {
    quotient_ring<quotient_ring<>> ring{
        {1, 2},
        {3, 4}
    };
    std::cout << ring << '\n'; // (1%2)%(3%4)
}

Might I suggest putting some spaces in the output (like (1 % 2) % (3 % 4)) to make it more readable?



来源:https://stackoverflow.com/questions/55943386/c-friend-operator-template-specialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!