3

由于与我一起使用通用代码的许多学生在理解正确的流运算符重载方面存在一些问题,因此我尝试创建一个帮助模板(不知道这是否是一个真正的 mixin)来简化代码并确保正确的运算符实现。它来了:

template<typename T> struct IoEnabled {
  friend std::ostream& operator<<(std::ostream& out, T const& val) {
    return val.print(out);
  }

  friend std::istream& operator>>(std::istream& in, T& val) {
    return val.scan(in);
  }

  friend QTextStream& operator<<(QTextStream& out, T const& val) {
    return val.print(out);
  }

  friend QTextStream& operator>>(QTextStream& in, T& val) {
    return val.scan(in);
  }

  friend QDebug operator<<(QDebug dbg,T const& val){
    std::stringstream myStream;
    myStream << val;
    dbg.nospace() << myStream.str().c_str();
    return dbg;
  }
};

继承类:

class Foo: private IoEnabled<Foo> {
  protected:
   int mData;

  public:
    template<typename U>
    U& scan(U& in) {
      in >> mData;
      return in;
    }

    template<typename U>
    U& print(U& out) const {
      out << mData;
      return out;
    }
}

就我目前所看到的而言,这种实现的缺点:

  • 不适用于第 3 方类型
  • 包括继承,因此与 IoClass 紧密耦合,尽管不是每个用户都可能需要某种类型的 Io

起起伏伏:

  • 有用 ;-)
  • 可以添加类似的流类,而无需修改所有类,也无需为每个类编写特定的新代码

由于我在使用 mixin 方面不是很有经验,并且偶尔会违反编码准则,所以我想知道这是否是 mixin 的适当用法,或者如何使用另一种更合适的方法获得类似的效果技术。

非常感谢,马丁

4

1 回答 1

2

如果他们可以编写scan模板print函数,他们还不如直接编写模板运算符,跳过这整个愚蠢的 mixin 业务。

struct Foo {
    int mData;
    Foo() : mData(mData) {}
};

template <typename OutputStream>
OutputStream& operator<<(OutputStream& stream, const Foo& data) {
    stream << data.mData;
    return stream;
}

template <typename InputStream>
InputStream& operator>>(InputStream& stream, Foo& data) {
    stream >> data.mData;
    return stream;
}

此外,这种特殊的 QDebug 重载看起来完全没有必要和错误。

于 2011-10-12T15:43:20.257 回答