Здравствуйте, 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;