Здравствуйте, Erop, Вы писали:
E>1) писать что-то своё в std нехорошо.
E>2) AFAIK, std::hex, как и другие манипуляторы, это просто функция получающая на вход ссылку на поток, и возвращающая её же. Например, std::ios_base& my_hex( std::ios_base& ). Эта функция может что-то сделать с потоком и только. Так что это просто такая форма вызова каких-то методов потока. То есть если ты можешь написать код, который переводит поток в состояние ХХХ, то можешь и написать манипулятор ХХХ, а иначе фигушки.
E>3) АFAIK, опять же, сишные потоки перевести в такое состояние, чтобы выдавались бинарные числа нельзя.
E>4) Но можно захачить. Написать шаблонную проксю, вокруг ссылки на поток, такую, что она будет выводить числа в бинарном виде + шаблонную же функцию-переключалку:E>template<typename TStream> class CBinStreamProxy {
E> TStream& stream;
E>public:
E> CBinStreamProxy( TStream& str ) : stream( str ) {}
E> CBinStreamProxy& operator << ( int i ) { out( i ); return *this; }
E> // тут для всех интегральных типов, либо можно как-то автоматизировать
E> template<typename TArg>
E> CBinStreamProxy& operator << ( TArg arg ) { stream << arg; return *this; }
E> // тут повторяем нужный интерфейс потока. Например преобразование к bool и т. д.
E>private:
E> template<typename TNumber>
E> void out( TNumber number ) { /* реализация */ }
E>};
E>enum enum_of_bin { bin };
E>template<typename TStream> CMyProxyStream<TStream> operator << (TStream& dst, enum_of_bin ) { return dst; }
На самом деле не надо никаких проксей, такие вещи делаются вполне стандартно через локали. За вывод чисел отвечает std::num_put. Надо написать его наследника, выводящего в зависимости от флага числа в нужном формате (переписать функции do_put), воткнуть его в локаль вместо std::num_put, выставить эту локаль потоку (вызвав метод imbue). В выставлять/снимать флаг в этом самопальном фасете (далее my_numbin_facet) можно примерно так:
void set_bin_mode(std::basic_ostream<CharType>& s, bool yes)
{
std::locale loc(s.getloc());
std::use_facet<my_numbin_facet<CharType> >(loc).set_bin_mode(yes);
s.imbue(loc);
}
Или, если хочется, проверять наличие нужного фасета с помощью std::has_facet и возвращать ошибку по-другому (use_facet кидает какое-то исключение).
При желании можно, конечно, запихать set_bin_mode в манипулятор, но тут возникает другая проблема — hex и dec про него ничего не знают, обратно переключать не смогут. Придется их тогда тоже переписать — IMHO, овчинка выделки не стоит, потому что при переписывании думаю вылезет еще одна проблема.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.