Re[2]: Необычные typedef
От: Кодт Россия  
Дата: 29.10.05 09:06
Оценка: 1 (1)
Здравствуйте, quantez, Вы писали:

Q>Пользоваться можно примерно так:

Q>int main()
Q>{
Q>    QTSMFI manipulator = &QTextStream::putInt;


Q>    QTextStream* stream = getStream();  // Взять откуда-нибудь поток.
Q>    (stream->*manipulator)( 18 );       // Вызвать функцию-член объекта *stream, на которую 
Q>                                        // указывает f (т. е. QTextStream::putInt)

Q>    // Или так
Q>    QTextStream& ref = getStreamRef();
Q>    (ref.*manipulator)( 20 );
Q>}


Скорее, вот так. (К сожалению, сам никогда библиотекой QT не пользовался — поэтому домыслы по аналогии с STL).

Манипуляторы — это функции, подмешиваемые во ввод/вывод потока:
cout << setfill('*') << setwidth(10) << 123 << endl;
// *******123

Для этого, во-первых, переопределяются операторы << и >>, а во-вторых, манипуляторы с аргументами возвращают некий функтор (объект, связывающий эти аргументы и принимающий на вход поток).

Нуль-арный манипулятор — проще всего:
// где-то есть такой оператор...
QTextStream& operator << (QTextStream& s, QTextStreamFunction f)
{
  return f(s);
}

// пишем собственный манипулятор
QTextStream& http_header_endl(QTextStream& s)
{
  s << "\r\r";
  s.flush();
  return s;
}

int main()
{
  QTextStream cgi;
  ....
  cgi << "404 Not found" << http_header_endl;
}


Унарные — как я уже сказал, требуют некий промежуточный объект. Писать классы таких объектов каждый раз — может быть лениво, поэтому воспользуемся шаблонами.
// функтор
template<class A>
struct qtsmf_binder // qts(tream)m(ember)f(unction)
{
  typedef void (QTextStream::*F)(A); // указатель на функцию-член
  F f_;
  A a_;

  qtsfm_binder(F f, A a) : f_(f), a_(a) {}

  QTextStream& operator()(QTextStream& s) const // сам функтор - это уже нуль-арный манипулятор
  {
    (s.*f_)(a_);
    return s;
  }
};
// порождающая функция (чтобы не вписывать тип вручную, а выводить его)
template<class A> qtsmf_binder<A> make_manip(void (QTextStream::*f)(A), A a)
{
  return qtsfm_binder<A>(f,a);
}

// оператор, принимающий наш манипулятор
template<class A>
QTextStream& operator << (QTextStream& s, qtsfm_binder<A> f)
{
  return f(s);
}

// создадим манипулятор с типичным значением
static qtsmf_binder<int> yet_another_hex (&QTextStream::setIntegerBase, 16);

int main()
{
  QTextStream out;
  ....
  out << make_manip(&QTextStrean::setIntegerBase,16) << 0xDEADBEEF;
  out << yet_another_hex << 0xBADC0DE;
  out << hex << 0xB00B5;
}
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.