Здравствуйте!
Реально ли сделать такое без залезания в кишки iostreams, как-нибудь в сторонке?
Мне всегда не хватало такого, но как-то не заморачивался. А тут сделал подсистему вывода для своего проекта — попроще в реализации, без развесистой иерархии классов, но с той же концепцией — operator ostream inserter, методы потока и манипуляторы вывода, совместимой с iostreams по всем базовым прикладным вещам: методам потоков, флагам "ios...", манипуляторам и тп — она совместима со стандартной библиотекой. Бонус в том, что не надо много нового изучать, и по большей части можно заглянуть в доку на стандартные потоки и всё там найти.
Так вот, добавил я там немного своих расширений:
манипулятор bin, наравне с hex и dec;
отдельно сделал регистр префикса — манипуляторы uppercasebase, lowercasebase — мне hex'ы всегда нравились в верхнем регистре, а вот префикс (и для bin'ов тоже) — в нижнем — так его хорошо видно, а когда регистр префикса такой же, как у числа, то он сливается с числом и парсить глазами зело труднее;
префикс для двоичных чисел — 0b;
заменил префикс для восьмеричных чисел — с просто нуля на 0o (ноль-О) — чисто для унификации с 0x и 0b;
манипулятор permanent (или как-то так — не помню точно, а исходников сейчас нет под рукой) — насколько я понял из описаний стандартных манипуляторов — они действуют только на один последующий вывод и потом параметры вывода сбрасываются до тех, что установлены для потока. Для потока же постоянные опции устанавливаются при помощи методов потока, через флаги в т.ч. и т.п., что всегда было мне зело неудобно и всегда хотелось устанавливать это манипуляторами. Вот и сделал манипулятор permanent для удобной настройки, он делает все ранее заданные временные опции постоянными. Выглядит так:
cout<<hex<<width(8)<<fill('0')<<permanent;
еще хотелка, думаю, скоро реализую — сделать отдельно binfill, hexfill, octfill, а xfill устанавливает fill char для всех троих, и отдельно decfill — для установки символа заполнения для десятичных чисел — потому как bin/hex обычно хочется дополнять нулями, чтобы понимать, где какой разряд, а в случае с десятичными числами, интересует само число и ведущие нули только мешают (а в случае префиксирования при выводе восьмеричных чисел простым нулем это еще и небольшая мина замедленного действия). Ну и числа вообще, как по мне, должны выравниваться другими символами, нежели строки и прочее нечисловое;
Вообщем, сделал я всё это, и понравилось мне это. И стал я активно пользоваться. Только вот код стал уже непереносим на стандартные потоки. В принципе, у меня для вывода предусмотрен интерфейс типа IWritter, и я сделал биндинги для стандартных потоков, но вот стало интересно, а можно ли стандартные потоки расширить, чтобы реализовать мои хотелки без моих прокладок, а в виде расширений стандартных потоков?
Так-то и то и то вроде как прокладки, но в текущей реализации у меня есть MyOstream и для него биндинги StdOstreamWritter/StdCoutWritter/StdCerrWritter и надо их настраивать перед стартом программы, что неудобно. А хочется, чтобы подключил какой-то хидер — и всё, все фичи присосались автоматом ко всем реализациям std::ostream