使用mixin(?)使流i / o更容易

时间:2011-10-12 15:16:12

标签: c++ templates generics mixins crtp

由于我在公共代码上工作的许多学生在理解正确的流操作符重载方面存在一些问题,因此我尝试创建一个帮助器模板(不知道这是否是真正的混合)以方便代码并确保正确的操作符实现。它来了:

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;
    }
}

目前我看到这个实现的缺点:

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

ups:

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

由于我对mixins的使用不是很有经验并且偶尔会违反编码指南,我想知道这是否适合使用mixin或者如何获得类似的效果另一种更合适的技术。

非常感谢,马丁

1 个答案:

答案 0 :(得分:2)

如果他们可以编写scanprint模板函数,他们也可以直接编写模板化运算符,跳过整个愚蠢的混合业务。

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重载看起来完全没必要和错误。