Использование миксина (?) для упрощения потокового ввода/вывода

Поскольку многие студенты, с которыми я работаю над общим кодом, имеют некоторые проблемы с пониманием правильной перегрузки оператора потока, я попытался создать вспомогательный шаблон (не знаю, настоящий ли это миксин), чтобы упростить код и обеспечить правильную реализацию оператора. Вот оно:

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 для определенного типа.

Взлеты:

  • Оно работает ;-)
  • Подобные потоковые классы могут быть добавлены без изменения всех классов и без написания отдельного нового кода для каждого класса.

Поскольку я не очень опытен в использовании миксинов и склонен время от времени нарушать правила кодирования, я хотел бы знать, является ли это подходящим использованием миксина или как можно получить аналогичный эффект с другим, более подходящим. техника.

Большое спасибо, Мартин


person Martin    schedule 12.10.2011    source источник


Ответы (1)


Если они могут писать scan и print шаблонные функции, они могут также напрямую писать шаблонные операторы, пропуская всю эту глупую мешанину.

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 выглядит совершенно ненужной и неправильной.

person Cat Plus Plus    schedule 12.10.2011
comment
ИМХО: полностью шаблонные операторы потока, как вы предлагаете, могут вызвать у вас большие проблемы, как мне сказали некоторое время назад, и я тоже испытал stackoverflow.com/questions/4195764/. - person Martin; 12.10.2011
comment
Кроме того, QDebug очень удобен для отладки (нет шаша, красный цвет, все типы данных QT уже поддерживаются...). К сожалению, его нельзя перегрузить, используя обычный синтаксис. Чтобы написать qDebug() ‹‹, как это предлагается в фреймворке qt, нужно пойти по пути, предложенному в doc.qt.nokia.com/latest/qdebug.html. - person Martin; 12.10.2011
comment
Также для ваших шаблонов вам все равно придется вызывать аксессоров или подружить их. - person Martin; 12.10.2011