使用 mixin (?) 使流 I/O 更容易

发布于 2024-12-09 18:04:20 字数 1468 浏览 1 评论 0原文

由于与我一起处理通用代码的许多学生在理解正确的流运算符重载方面存在一些问题,因此我尝试创建一个帮助器模板(不知道这是否是真正的 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 对于某种类型

ups:

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

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

非常感谢,马丁

Since many students I work with on common code have some problems comprehending proper stream operator overloading, I tried to create a helper template (don't know if this is a real mixin) to facilitate the code and insure correct operator implementation. Here it comes:

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

Inheriting class:

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

The downsides of this implementation as far as I see them at the moment:

  • Does not work for 3rd party types
  • Includes inheritance and thus tight coupling with the IoClass although not every user might need
    Io for a certain type

The ups:

  • It works ;-)
  • Similar stream classes can be added without modifying all classes and withou writing specific new code for every class

Since I'm not very experienced in the usage of mixins and tend to violate coding guidelines once in a while, I'd like to know if this is an appropriate usage of a mixin or how one could obtain a similar effect with another more suitable technique.

Many Thanks, Martin

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疧_╮線 2024-12-16 18:04:20

如果他们可以编写 scanprint 模板函数,他们也可以直接编写模板化运算符,从而跳过整个愚蠢的 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 重载看起来完全没有必要而且是错误的。

If they can write scan and print template functions, they might as well write templated operators directly, skipping this entire silly mixin business.

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

Also, that special-cased QDebug overload looks entirely unnecessary and wrong.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文