Namespaces
Variants

std::num_put<CharT,OutputIt>:: put, std::num_put<CharT,OutputIt>:: do_put

From cppreference.net
std::num_put
Member functions
num_put::put num_put::do_put
Определено в заголовке <locale>
(1)
public :

iter_type put ( iter_type out, std:: ios_base & str,

char_type fill, bool val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, long val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, long long val ) const ;
(начиная с C++11)
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, unsigned long val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, unsigned long long val ) const ;
(начиная с C++11)
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, double val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, long double val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, const void * val ) const ;
(2)
protected :

virtual iter_type do_put ( iter_type out, std:: ios_base & str,

char_type fill, bool val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, long val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, long long val ) const ;
(начиная с C++11)
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, unsigned long val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, unsigned long long val ) const ;
(начиная с C++11)
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, double val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, long double val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, const void * val ) const ;
1) Открытая функция-член, вызывает защищенную виртуальную функцию-член do_put самого производного класса.
2) Записывает символы в выходную последовательность out , которые представляют значение val , отформатированное в соответствии с флагами форматирования str. flags ( ) и аспектами std::numpunct и std::ctype локали, установленной в потоке str . Эта функция вызывается всеми операторами форматированного вывода в поток, такими как std:: cout << n ; .

Преобразование происходит в четыре этапа:

Содержание

Этап 1: выбор спецификатора преобразования

  • Флаги формата ввода-вывода получаются, как если бы с помощью
fmtflags basefield = ( str. flags ( ) & std:: ios_base :: basefield ) ;
fmtflags uppercase = ( str. flags ( ) & std:: ios_base :: uppercase ) ;
fmtflags floatfield = ( str. flags ( ) & std:: ios_base :: floatfield ) ;
fmtflags showpos = ( str. flags ( ) & std:: ios_base :: showpos ) ;
fmtflags showbase = ( str. flags ( ) & std:: ios_base :: showbase ) ;
fmtflags showpoint = ( str. flags ( ) & std:: ios_base :: showpoint ) ;
**Примечание:** Весь представленный код является C++ кодом внутри тегов ` `, поэтому в соответствии с инструкциями он не был переведен. HTML структура и атрибуты также сохранены без изменений.
  • Если тип val является bool :
    • Если boolalpha == 0 , преобразует val в тип int и выполняет целочисленный вывод.
    • Если boolalpha ! = 0 , получает std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) если val == true или std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) если val == false , и выводит каждый последующий символ c этой строки в out с помощью * out ++ = c . В этом случае дальнейшая обработка не выполняется, функция возвращает out .
  • Если тип val является целочисленным типом, выбирается первый применимый вариант из следующих:
    • Если basefield == oct , будет использоваться спецификатор преобразования % o .
    • Если basefield == hex && ! uppercase , будет использоваться спецификатор преобразования % x .
    • Если basefield == hex , будет использоваться спецификатор преобразования % X .
    • Если тип val знаковый, будет использоваться спецификатор преобразования % d .
    • Если тип val беззнаковый, будет использоваться спецификатор преобразования % u .
  • Для целочисленных типов модификатор длины добавляется к спецификации преобразования при необходимости: l для long и unsigned long , ll для long long и unsigned long long (начиная с C++11) .
  • Если тип val является типом с плавающей точкой, выбирается первый применимый вариант из следующих:
  • Если floatfield == std:: ios_base :: fixed , будет использоваться спецификатор преобразования % f .
(до C++11)
  • Если floatfield == std:: ios_base :: fixed && ! uppercase , будет использоваться спецификатор преобразования % f .
  • Если floatfield == std:: ios_base :: fixed , будет использоваться спецификатор преобразования % F .
(начиная с C++11)
  • Если floatfield == std:: ios_base :: scientific && ! uppercase , будет использоваться спецификатор преобразования % e .
  • Если floatfield == std:: ios_base :: scientific , будет использоваться спецификатор преобразования % E .
(начиная с C++11)
  • Если ! uppercase , будет использован спецификатор преобразования % g .
  • Иначе будет использован спецификатор преобразования % G .
Также:
  • Если тип val long double , к спецификатору преобразования добавляется модификатор длины L .
  • Если тип val является типом с плавающей точкой и floatfield ! = ( ios_base :: fixed | ios_base :: scientific ) (начиная с C++11) , добавляется модификатор точности, устанавливаемый в значение str. precision ( ) . В противном случае точность не указывается.
  • Для целочисленных и типов с плавающей точкой, если установлен showpos , модификатор + добавляется в начало.
  • Для целочисленных типов, если установлен showbase , модификатор # добавляется в начало.
  • Для типов с плавающей точкой, если установлен showpoint , модификатор # добавляется в начало.
  • Если тип val является void * , будет использоваться спецификатор преобразования % p
  • Строка узких символов создаётся как при вызове std:: printf ( spec, val ) в локали "C", где spec — выбранный спецификатор преобразования.

Этап 2: преобразование с учетом локали

  • Каждый символ c полученный на Этапе 1, кроме десятичной точки '.' , преобразуется в CharT вызовом std:: use_facet < std:: ctype < CharT >> ( str. getloc ( ) ) . widen ( c ) .
  • Для арифметических типов символ разделителя тысяч, полученный из std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . thousands_sep ( ) , вставляется в последовательность согласно правилам группировки, предоставляемым std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) .
  • Символы десятичной точки ( '.' ) заменяются на std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . decimal_point ( ) .

Этап 3: padding

  • Флаг выравнивания получается как будто бы с помощью std :: fmtflags adjustfield = ( flags & ( std:: ios_base :: adjustfield ) ) и анализируется для определения позиции заполнения следующим образом:
    • Если adjustfield == std:: ios_base :: left , заполнение будет после значения.
    • Если adjustfield == std:: ios_base :: right , заполнение будет перед значением.
    • Если adjustfield == std:: ios_base :: internal и в представлении встречается символ знака, заполнение будет после знака.
    • Если adjustfield == std:: ios_base :: internal и представление на Этапе 1 начиналось с 0x или 0X, заполнение будет после x или X.
    • В противном случае заполнение будет перед значением.
  • Если str. width ( ) не равно нулю (например, только что использовался std::setw ) и количество символов CharT после Этапа 2 меньше, чем str. width ( ) , тогда копии символа fill вставляются в позицию, указанную для заполнения, чтобы довести длину последовательности до str. width ( ) .

В любом случае, str. width ( 0 ) вызывается для отмены эффектов std::setw .

Этап 4: вывод

Каждый последующий символ c из последовательности CharT из Стадии 3 выводится как если бы выполнялось * out ++ = c .

Параметры

out - итератор, указывающий на первый символ для перезаписи
str - поток для получения информации о форматировании
fill - символ заполнения, используемый при необходимости дополнения результатов до ширины поля
val - значение для преобразования в строку и вывода

Возвращаемое значение

out

Примечания

Ведущий ноль, сгенерированный спецификацией преобразования #o (результат комбинации std::showbase и std::oct например) не считается символом заполнения.

При форматировании значения с плавающей точкой в виде шестнадцатеричного представления (т.е. когда floatfield == ( std:: ios_base :: fixed | std:: ios_base :: scientific ) ), точность потока не используется; вместо этого число всегда выводится с достаточной точностью для точного представления значения.

(since C++11)

Пример

Вывод числа напрямую с использованием фасета и демонстрация пользовательского фасета:

#include <iostream>
#include <locale>
// this custom num_put outputs squares of all integers (except long long)
struct squaring_num_put : std::num_put<char>
{
    iter_type do_put(iter_type out, std::ios_base& str,
                     char_type fill, long val) const
    {
        return std::num_put<char>::do_put(out, str, fill, val * val);
    }
    iter_type do_put(iter_type out, std::ios_base& str,
                     char_type fill, unsigned long val) const
    {
        return std::num_put<char>::do_put(out, str, fill, val * val);
    }
};
int main()
{
    auto& facet = std::use_facet<std::num_put<char>>(std::locale());
    facet.put(std::cout, std::cout, '0', 2.71);
    std::cout << '\n';
    std::cout.imbue(std::locale(std::cout.getloc(), new squaring_num_put));
    std::cout << 6 << ' ' << -12 << '\n';
}

Вывод:

2.71
36 144

Реализация operator<< для пользовательского типа.

#include <iostream>
#include <iterator>
#include <locale>
struct base { long x = 10; };
template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os, const base& b)
{
    try
    {
        typename std::basic_ostream<CharT, Traits>::sentry s(os);
        if (s)
        {
            std::ostreambuf_iterator<CharT, Traits> it(os);
            std::use_facet<std::num_put<CharT>>(os.getloc())
                .put(it, os, os.fill(), b.x);
        }
    }
    catch (...)
    {
        // set badbit on os and rethrow if required
    }
    return os;
}
int main()
{
    base b;
    std::cout << b;
}

Вывод:

10

Отчёты о дефектах

Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 34 C++98 перегрузка для bool использовала несуществующие члены
truename и falsename из std::ctype
использовать эти члены
из std::numpunct
LWG 231 C++98 модификатор точности добавлялся только если
( flags & fixed ) ! = 0 или str. precision ( ) > 0
убраны эти условия
LWG 282 C++98 разделители тысяч вставлялись только
для целочисленных типов на этапе 2
также вставляются для
типов с плавающей точкой
LWG 4084 C++11 "NAN" и "INF" не могли быть выведены они могут быть выведены

Смотрите также

вставляет форматированные данные
(публичная функция-член std::basic_ostream<CharT,Traits> )