Re: вопрос проектирования
От: Кодт Россия  
Дата: 21.01.04 11:17
Оценка:
Здравствуйте, Oleg A. Bachin, Вы писали:

OAB>я только начинаю изучать С++, поэтому позникают вопросы правильности применения тех или иных методов...


OAB>задача такая:

OAB>есть несколько типов данный. под типом (в данном контексте) подразумеваю родной тип С++ (или stl) плюс тип форматирования (выравнивать влево/вправо, значащие нули/нет и т.д..).

OAB>также у каждого элемента кроме типа есть размер, т.е. его фиксированная длинна в буффере. (я еще не выбрал как удобнее будет работать через буффер или поток. поток вроде как логичнее, но могут быть проблеммы с итераторами. только об этом потом...)


Через поток — проще. Есть strstream, который выводит в строку.

Мне решение видится так:
template<class Data, class Fmt>
struct apply_fmt
{
  Data data; // пока что обойдемся без операторов приведения типа, как в auto_value.
};

template<class Data, class Fmt>
ostream& operator<< (ostream& ost, apply_fmt<Data,Fmt> const& v)
{
  return ostream << Fmt() << v.data;
}

Fmt — классы, экземпляры которых выводятся как команды для ostream.
Поскольку команды известны на стадии проектирования, то все детали запихаем
// отдельные команды

template<int w> struct fmt_setw {};

template<int w> ostream& operator<< (ostream& ost, fmt_setw<w> _)
{
  return ost << setw(w);
}

template<char f> struct fmt_setfill {};

template<char f> ostream& operator<< (ostream& ost, fmt_setfill<f> _)
{
  return ost << setfill(f);
}

template<int b> struct fmt_setbase {};

template<int b> ostream& operator<< (ostream& ost, fmt_setbase<b> _)
{
  return ost << setbase(b);
}

struct fmt_hex {};
inline ostream& operator<< (ostream& ost, fmt_hex _) { return ost << hex; }

struct fmt_dec {};
struct fmt_left {};
struct fmt_right {};
// и т.д.

// наконец, пустой формат
struct fmt_void {};

inline ostream& operator<< (ostream& ost, fmt_void _) { return ost; }

// связывание форматов
// можно воспользоваться Loki::TypeList или boost::что-то-там-щас-не-помню

template<class F1, class F2> struct fmt_chain {};

template<class F1, class F2> ostream& operator<< (ostream& ost, fmt_chain<F1,F2> _)
{
  return ost << F1() << F2();
}

#define FMT_CONS(f1,f2) fmt_pair< f1, f2 >
#define FMT_NULL fmt_void

#define FMT_LIST1(f1)          FMT_CONS(f1,FMT_NULL)
#define FMT_LIST2(f1,f2)       FMT_CONS(f1, FMT_LIST1(f2))
#define FMT_LIST3(f1,f2,f3)    FMT_CONS(f1, FMT_LIST2(f2,f3))
#define FMT_LIST4(f1,f2,f3,f4) FMT_CONS(f1, FMT_LIST3(f2,f3,f4))

Применение
typedef apply_fmt<unsigned long, FMT_LIST3(fmt_hex, fmt_setw<8>, fmt_setfill<'0'>)> hexulong;
hexulong n;
n.data = 0xdead;
cout << n;
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.