C++ 友元运算符模板特化
c++ friend operator template specialization
我有一个通用的 modulo 结构,称为 quotient_ring
。相关位如下所示。
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 << ')';
}
};
此运算符 <<
会打印类似 2
mod 7
的内容为 (2)%(7)
。我需要方括号的原因是 R
类型可以变得非常嵌套。但是,如果 R
只是一个算术类型,例如 long long
,我想不带括号打印。我发现实现此目的的一种方法如下。
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 tend to personally like template specialization more than branching on type traits.
为什么? if constexpr
是一个 编译时分支 。等效的 SFINAE 可读性要差得多。
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)
}
我是否建议在输出中添加一些空格(例如 (1 % 2) % (3 % 4)
)以使其更具可读性?
我有一个通用的 modulo 结构,称为 quotient_ring
。相关位如下所示。
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 << ')';
}
};
此运算符 <<
会打印类似 2
mod 7
的内容为 (2)%(7)
。我需要方括号的原因是 R
类型可以变得非常嵌套。但是,如果 R
只是一个算术类型,例如 long long
,我想不带括号打印。我发现实现此目的的一种方法如下。
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 tend to personally like template specialization more than branching on type traits.
为什么? if constexpr
是一个 编译时分支 。等效的 SFINAE 可读性要差得多。
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)
}
我是否建议在输出中添加一些空格(例如 (1 % 2) % (3 % 4)
)以使其更具可读性?