c ++朋友运算符模板专业化

时间:2019-05-01 22:15:18

标签: c++ operator-overloading friend template-specialization

我有一个称为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 << ')';
}

我认为这是一个很好的解决方案。但是,我想知道是否可以通过模板专门化来实现。我个人更喜欢模板专业化,而不是分支于类型特征。

1 个答案:

答案 0 :(得分:2)

  

我个人更喜欢模板专业化,而不是分支类型特征。

为什么? $ cat file OCCUPY 12 EVERY PIC 32(12). SUNNY OCCUPY 45 EVERY PIC X(21). SUNNY $ sed -Ez 's/(OCCUPY\s+[0-9]+\s+EVERY)\s+(PIC\s+[^)]+\))/\2 \1/g' file PIC 32(12) OCCUPY 12 EVERY. SUNNY PIC X(21) OCCUPY 45 EVERY. SUNNY $ sed -Ez 's/((\S+\s+){2}\S+)\s+(\S+\s+\S+\))/\3 \1/g' file PIC 32(12) OCCUPY 12 EVERY. SUNNY PIC X(21) OCCUPY 45 EVERY. SUNNY $ sed -Ez 's/(OCCUPY)\s+([0-9]+)\s+(EVERY)\s+(PIC)\s+([^)]+\))/\4 \5 \1 \2 \3/g' file PIC 32(12) OCCUPY 12 EVERY. SUNNY PIC X(21) OCCUPY 45 EVERY. SUNNY $ sed -Ez 's/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+\))/\4 \5 \1 \2 \3/g' file PIC 32(12) OCCUPY 12 EVERY. SUNNY PIC X(21) OCCUPY 45 EVERY. SUNNY 编译时分支。等效的SFINAE的可读性要差得多。

if constexpr

可能我建议在输出中放置一些空格(例如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) } )以使其更具可读性吗?