代码之家  ›  专栏  ›  技术社区  ›  sancho.s ReinstateMonicaCellio

对几个类重复使用一个操作符<<

  •  0
  • sancho.s ReinstateMonicaCellio  · 技术社区  · 4 年前

    我有两个类(这是从我实际的更复杂的案例中提取的)

    class ClUInt {
    public:
        ClUInt() : _i(2), _arr{1,2,3} {};
        ClUInt(const unsigned int ui) : _i(ui) {};
    private:
        unsigned int _i;
        double _arr[3];
    };
    
    class ClInt {
    public:
        ClInt() : _i(-2), _arr{-1,-2,-3} {};
        ClInt(const int i) : ClInt() { _i = i; };
    private:
        int _i;
        double _arr[3];
    };
    

    它们非常相似,但有一种用法 int 另一个呢 unsigned int 给会员 _i .

    我想超负荷工作 operator<< 例如。,

    std::ostream& operator<<(std::ostream& os, const ClInt & ci)
    {
        cout << ci._i << endl;
        cout << ci._arr[0] << endl;
        return os;
    }
    

    假设我希望两个类都有“相同”的重载。

    我怎样才能只写一次,这样更容易维护? 我想定义自己的演员阵容,但我不确定这是一条路要走。。。

    笔记:

    1. 认为 我没有机会让这两个类共享继承树的任何部分。

    2. 他们可能真的是 struct s、 因此,如果隐私影响答案,人们可以假设 _我 _arr public .

    3. 在实际案例中,两个 结构 s的“普通”成员数较多,分别是有签名的/无签名的。

    1 回复  |  直到 4 年前
        1
  •  3
  •   Aykhan Hagverdili    4 年前

    使用具有以下概念的模板:

    #include <concepts>
    #include <iostream>
    
    template<typename T>
    concept ClInteger = std::same_as<T, ClInt> || std::same_as<T, ClUInt>;
    
    template <ClInteger T>
    std::ostream& operator<<(std::ostream& os, const T & ci)
    {
        std::cout << ci._i << '\n';
        std::cout << ci._arr[0] << '\n';
        return os;
    }
    

    注意,这个操作符必须是这些类的朋友,才能访问它们的私有字段。
    LIVE

        2
  •  2
  •   AVH    4 年前

    你可以尝试创建一个模板 operator<< 这只适用于使用SFINAE的这两种类型。例如。:

    template <class T,
      std::enable_if_t<
          std::is_same<ClInt, std::decay_t<T>>::value
          or std::is_same<ClUInt, std::decay_t<T>>::value
        , int> = 0>
    std::ostream & operator<< (std::ostream & out, T const & obj) {
      out << obj._i << '\n';
      out << obj._arr[0] << '\n';
      return out;
    }
    

    上面的示例适用于C++14,但如果替换了以下内容,则可以使其与C++11一起使用: std::decay_t<T> 具有 typename std::decay<T>::type .

    注:我更换了 std::endl 具有 '\n' ,因为您可能不想每次都刷新输出流。看见 C++: "std::endl" vs "\n" .

        3
  •  0
  •   Ulrich Eckhardt    4 年前

    也许这只是巧合,但你们两个班有很多共同之处。那么,为什么不把它们变成模板呢:

    template<typename integer_type>
    class IntegerClass
    {
        /// ... further code elided
    
        friend ostream& operator<<(ostream& out, IntegerClass const& obj)
        {
            return out
                << obj._i << endl
                << obj._arr[0] << endl;
        }
        integer_type _i;
        double _arr[3];
    };
    
    // optional typedefs
    // These are a matter of taste, not actually mine.
    typedef IntegerClass<unsigned int> ClUInt;
    typedef IntegerClass<signed int> ClInt;