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.