Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

The Boost Format library

Boost , ,

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

boost.png (6897 bytes)The Boost Format library

Класс формата<<boost/format.hpp>>обеспечивает типоподобное форматирование, безопасным способом, который позволяет выводить определенные пользователем типы.


Synopsis

Объект формата строится из строки формата, а затем приводится аргументация посредством повторных вызовов оператору%..
Каждый из этих аргументов затем преобразуется в строки, которые, в свою очередь, объединяются в одну строку, согласно строке формата.

cout << boost::format("writing %1%,  x=%2% : %3%-th try") % "toto" % 40.23 % 50; 
     // prints "writing toto,  x=40.230 : 50-th try"

How it works

  1. При вызовеформата (форматов), где s — строка формата, он конструирует объект, который парсирует строку формата и ищет в ней все директивы и готовит внутренние структуры к следующему шагу.
  2. Затем, либо сразу, как в
    cout << format("%2% %1%") % 36 % 77;
    
    , либо позже, как в
    format fmter("%2% %1%");
    fmter % 36; fmter % 77;
    
    , выподаетепеременные в форматтер.
    эти переменные сбрасываются во внутренний поток, состояние которого устанавливается в соответствии с заданными параметрами форматирования в строке формата - если таковые имеются - и объект формата хранит результаты строки для последнего шага.
  3. После подачи всех аргументов вы можете сбросить объект формата в поток или получить его значение строки, используя функциюstr(), или бесплатную функциюstr(const format&)в пространстве именboost. Строка результата остается доступной в объекте формата до тех пор, пока не будет принят другой аргумент, и в это время она будет восстановлена.
    // fmter was previously created and fed arguments, it can print the result :
    cout << fmter ;  
    // You can take the string result :
    string s  = fmter.str();
    // possibly several times :
    s = fmter.str( );
    // You can also do all steps at once :
    cout << boost::format("%2% %1%") % 36 % 77; 
    // using the str free function :
    string s2 = str( format("%2% %1%") % 36 % 77 );
    
  4. Опционально, после этапа 3, вы можете повторно использовать объект формата и перезапустить на этапе 2 :fmter % 18 % 39;
    для форматирования новых переменных с той же строкой формата, сохраняя дорогостоящую обработку, участвующую на этапе 1.
All in all, the format class translates a format-string (with eventually printf-like directives) into operations on an internal stream, and finally returns the result of the formatting, as a string, or directly into an output stream.

Examples

using namespace std;
using boost::format;
using boost::io::group;
  • Простой вывод с переупорядочением:
    cout << format("%1% %2% %3% %2% %1% \n") % "11" % "22" % "333"; // 'simple' style.
    
    Оригинальное название: 11 22 333 22 11 \n
  • Более точное форматирование с позиционными директивами Posix-printf:
    cout << format("(x,y) = (%1$+5d,%2$+5d) \n") % -23 % 35;     // Posix-Printf style
    
    Он печатает : "(x,y) = ( -23, +35) \n"
  • Классическая директива printf, без переупорядочения :
    cout << format("writing %s,  x=%s : %d-th step \n") % "toto" % 40.23 % 50; 
    
    Он печатает: «письменный тото, x=40.23 : 50-й шаг \n»
  • Несколько способов выразить одно и то же:
    cout << format("(x,y) = (%+5d,%+5d) \n") % -23 % 35;
    cout << format("(x,y) = (%|+5|,%|+5|) \n") % -23 % 35;
    cout << format("(x,y) = (%1$+5d,%2$+5d) \n") % -23 % 35;
    cout << format("(x,y) = (%|1$+5|,%|2$+5|) \n") % -23 % 35;
    
    все эти отпечатки: "(x,y) = (-23, +35) \n"
  • Использование манипуляторов для изменения формата-струны :
    format fmter("_%1$+5d_ %1$d \n");
    format fmter2("_%1%_ %1% \n");
    fmter2.modify_item(1, group(showpos, setw(5)) ); 
    cout << fmter % 101 ;
    cout << fmter2 % 101 ;
    
    Оба печатают одинаково: «_ +101_ 101 \n»
  • Используя манипуляторы с аргументами:
    cout << format("_%1%_ %1% \n") % group(showpos, setw(5), 101);
    
    Манипуляторы применяются при каждом возникновении %1%, и таким образом он печатает: «_+101_+101\n»
  • Новая функция форматирования: «абсолютные таблицы», полезные внутри петель, для обеспечения того, чтобы поле печаталось в одном положении от одной строки к другой, даже если ширина предыдущих аргументов может сильно различаться.
    for(unsigned int i=0; i < names.size(); ++i)
        cout << format("%1%, %2%, %|40t|%3%\n") % names[i] % surname[i] % tel[i];
    
    Для некоторых std::vectorимена,фамилииител(см. sample_new_features.cpp) он печатает :
    Marc-François Michel, Durand,           +33 (0) 123 456 789
    Jean, de Lattre de Tassigny,            +33 (0) 987 654 321
    

Sample Files

Программаsample_formats.cppдемонстрирует простое использование формата.

sample_new_features.cppиллюстрирует несколько функций форматирования, которые были добавлены в синтаксис printf, такие как простые позиционные директивы, центрированное выравнивание и «табулации».

sample_advanced.cppдемонстрирует использование расширенных функций, таких как повторное использование и модификация, форматирование объектов и т.д.

Иsample_userType.cppпоказывает поведение библиотекиформатана определяемых пользователем типах.


Syntax

повышение::форматформат-струна) %arg1%arg2%...%argN

Формат-струнасодержит текст, в котором специальные директивы будут заменены строками, вытекающими из форматирования данных аргументов.
Унаследованный синтаксис в мирах C и C++ — это тот, который используется printf, и, таким образом, формат может использовать прямые строки формата printf и производить тот же результат (почти во всех случаях). смотретьНесоответствия с printfдля деталей
Этот основной синтаксис был расширен, чтобы позволить новые функции, а также адаптироваться к контексту потоков C++. Таким образом, формат принимает несколько форм директив в строках формата:

  • Наследие строк формата printf :%spec, гдеspecявляется спецификацией форматаprintf
    specпередает параметры форматирования, такие как ширина, выравнивание, числовое основание, используемое для форматирования чисел, а также другие конкретные флаги. Но классическийтипоспецифическийфлаг printf имеет более слабое значение в формате. Он просто устанавливает соответствующие флаги во внутреннем потоке и/или параметры форматирования, но не требует, чтобы соответствующий аргумент был определенного типа.
    например: спецификация2$x, означающая «аргумент печати No 2, который является интегральным числом, в hexa» для printf, просто означает «аргумент печати 2 с флагами потокового базового поля, установленными наhex» для формата.
  • % |спецификация|, гдеспецификацияявляется спецификацией формата printf.
    Этот синтаксис, очерченный трубами, вводится для улучшения читаемости строки формата, но в первую очередь для того, чтобы сделать символ преобразованиятипанеобязательным в спецификации. Эта информация не нужна с переменными C++, но с прямым синтаксисом printf, необходимо всегда давать символ преобразования типа, просто потому, что этот символ имеет решающее значение для определения конца спецификации формата.
    например: «% | 5 |» будет форматировать следующую переменную с шириной, установленной на 5, и левым выравниванием точно так же, как следующие директивы printf: «%-5g», «%-5f», «%-5s».
  • %N%
    This simple positional notation requests the formatting of the N-th argument - wihout any formatting option.
    (It's merely a shortcut to Printf's positional directives (like "%N$s"), but a major benefit is that it's much more readable, and does not use a "type-conversion" character)
On top of the standard printf format specifications, new features were implemented, like centered alignment. See new format specification for details.

printf format specifications

Спецификации формата printf, поддерживаемые Boost.format, соответствуют Unix98. Open-group printfточный синтаксис, а не стандартный C printf, который не поддерживает позиционные аргументы. (Обычные флаги имеют одинаковое значение в обоих, поэтому это не должно быть головной болью для кого-либо)
Обратите внимание, что использование спецификаций позиционного формата(например,%3$+d)смешивается с непозиционными(например,%+d)в одной строке формата является ошибкой.
В спецификации Open-group ссылка на один и тот же аргумент несколько раз (например,"%1$d%1$d") имеет неопределенное поведение. Поведение Boost.format в таких случаях заключается в том, чтобы каждый аргумент перекликался с любым количеством раз. Единственным ограничением является то, что он ожидает точноPаргументов,Pявляется максимальным числом аргументов, используемым в строке формата. (например, для "%1$d%10$d",P== 10 ).
Подача большего или меньшего количества аргументовРвызывает исключение. (если не указано иное, см.исключения)



Спецификацияспецификацияимеет вид:N$флагиширинаточностьтип-чар

Поля, заключенные в квадратные скобки, являются необязательными. Каждое из этих полей объясняется по одному в следующем списке:

  • N$(необязательное поле) указывает, что спецификация формата применяется к аргументуN.Спецификация позиционного формата
    Если этого нет, аргументы принимаются один за другим. (и это ошибка, чтобы позже предоставить номер аргумента)
  • flags is a sequences of any of those :
    Флаг Значение Воздействие на внутренний поток
    '-' левое выравнивание N/A (применяется позже в строке)
    '=' центрированное выравнивание N/A (применяется позже на строке)
    - примечание: добавленная функция, не в printf -
    '_' внутреннее выравнивание устанавливает внутреннее выравнивание
    - примечание: добавленная функция, не в printf -
    '+' Показать знак даже для положительных чисел [править править код]
    '#' показать числовое основание и десятичную точку ,,,,,,.
    '0' Площадка с 0 (вставлена после знака или базового индикатора) Если не выровняется слева, вызываетsetfill('0')и устанавливаетвнутренний
    Дополнительные действия предпринимаются после преобразования потока для обработкиопределяемого пользователем вывода.
    '+' Если строка не начинается с+или-, вставьтепространствоперед преобразованной строкой N/A (применяется позже в строке)
    Different to printf's behaviour : it is not affected by internal alignment
  • ширинаопределяет минимальную ширину для струны, получающейся в результате преобразования. Если необходимо, строка будет проложена с выравниванием и заполнением символов либо установлена на потоке через манипуляторы, либо указана строкой формата (например, флаги '0', '-', ..)
    Обратите внимание, что ширина не просто устанавливается на потоке преобразования. Для поддержки выводаопределяемых пользователем типов(которые могут вызыватьоператора<<много раз на нескольких элементах) ширина обрабатывается после преобразования потока всего объекта аргумента в код класса формата.
  • точность(предваряется точкой), устанавливает точность потока
    • При выводе числа плавающего типа он устанавливает максимальное количество цифр
      • после десятичной точки, когда в фиксированном или научном режиме
      • в общем, когда в режиме по умолчаниюобщий режим', как%g
    • При использовании с тип-чаромsилиSтребуется другое значение: конверсионная строка усечена доточностипервых загонов. (Обратите внимание, что после усечения делается прокладка доширины.)
  • type-char. it does not impose the concerned argument to be of a restricted set of types, but merely sets the flags that are associated with this type specification.
    Тип-Чар Значение Воздействие на поток
    p или x шестидесятичный выход гекс
    О октальный выход окт
    е научный формат Устанавливает биты флоатфилданаучным
    f формат фиксированного поплавка Устанавливает биты флоатфилда нафиксированный
    г Общий формат -default- float unsetвсе биты флоатфилда
    X, EилиG Тот же эффект, что и их строчные аналоги, но с использованием строчных букв для вывода чисел. (экспоненты, шестизначные цифры, ..) те же эффекты, что'x','e', или'g',плюсверхний регистр
    d, iилиu десятичныйвыходной тип Устанавливает биты базового поля наdec
    sилиS струнный выход точностьспецификация не установлена, и ее значение переходит во внутреннее поле для последующего усечения.Точностьобъяснение выше
    cилиC 1-символьный выход Используется только первый символ строки преобразования.
    % напечатать символ% N/A

    Обратите внимание, что спецификация типа «n» игнорируется (и поэтому является соответствующим аргументом), потому что она не подходит в этом контексте.
    Также поддерживаются модификаторы printf 'l', 'L' или 'h' (для обозначения широких, длинных или коротких типов) (и просто не оказывают влияния на внутренний поток).

new format-specifications

  • Как указано в таблице флагов, были добавлены центрированные и внутренние флаги выравнивания=и_.
  • %{nt}, гдеnявляется положительным числом, вставляетабсолютную таблицу. Это означает, что при необходимости формат будет заполнять строку символами, пока длина строки, созданной до сих пор, не достигнетnсимволов. (см.примеры)
  • % |nTX|вставляет табуляцию таким же образом, но используяXв качестве символа заполнения вместо текущего «заполняющего» шара потока (который являетсяпространствомдля потока в состоянии по умолчанию)

Differences of behaviour vs printf

Suppose you have variables x1, x2 (built_in types, supported by C's printf),
and a format string s intended for use with a printf function this way :
printf(s, x1, x2);

In almost all cases, the result will be the same as with this command :
cout << format(s) % x1 % x2;

Но поскольку некоторые спецификации формата printf плохо переводятся в параметры форматирования потоков, есть несколько заметных недостатков в том, как Boost.format эмулирует printf.
В любом случае классформатадолжен спокойно игнорировать неподдерживаемые опции, так что строки формата printf всегда принимаются форматом и производят почти такой же выход, как printf.


Here is the full list of such differences :
  • '0'и''опции: printf игнорирует эти опции для нечисловых преобразований, но формат применяет их ко всем типам переменных. (Таким образом, можно использовать эти опции на определенных пользователем типах, например, рациональный класс и т.д.)
  • точностьдля аргументов интегральных типов имеет особое значение для printf :
    printf("(%5.3d)", 7) ;prints « (007) »
    Формат, как и потоки, игнорирует точный параметр для преобразования интегральных типов.
  • Вариантprintfс тысячами групповых символовне имеет эффекта в формате.
  • Ширина или точность, установленные на звездочку*, используются printf для чтения этого поля из аргумента. Например,printf("%1$d:%2$.*3$d:%4$.*3$d\n", час, минута, точность, сек);
    Этот класс пока не поддерживает этот механизм. Таким образом, такие поля точности или ширины незаметно игнорируются при разборе.
Also, note that the special 'n' type-specification (used to tell printf to save in a variable the number of characters output by the formatting) has no effect in format.
Thus format strings containing this type-specification should produce the same converted string by printf or format. It will not cause differences in the formatted strings between printf and format.
To get the number of characters in the formatted string using Boost.Format, you can use the size() member function :
format formatter("%+5d");
cout << formatter % x;
unsigned int n = formatter.size();

User-defined types output

Все флаги, переведенные в состояние потока, действуют рекурсивно в определенных пользователем типах. (флаги остаются активными, как и опция желаемого формата для каждой из операций, которые могут быть вызваны классом, определенным пользователем)

e.g., with a Rational class, we would have something like :
Rational ratio(16,9);
cerr << format("%#x \n")  % ratio;  // -> "0x10/0x9 \n"

Это другая история для других вариантов форматирования. Например, ширина установки относится к конечному выходу, произведенному объектом, а не к каждому из его внутренних выходов, и это хорошо:

cerr << format("%-8d")  % ratio;  // -> "16/9    "      and not    "16      /9       "
cerr << format("%=8d")  % ratio;  // -> "  16/9  "      and not    "   16   /    9   "


Но так же происходит с опциями 0 и '' (в отличие от '+', которые непосредственно переводятся в состояние потокаshowpos. Но таких флагов для нулевых и космических вариантов печати не существует
, и это менее естественно:

cerr << format("%+08d \n")  % ratio;  // -> "+00016/9"
cerr << format("% 08d \n")  % ratio;  // -> "000 16/9"
It is possible to obtain a better behaviour by carefully designing the Rational's operator<< to handle the stream's width, alignment and showpos paramaters by itself. This is demonstrated in sample_userType.cpp.

Manipulators, and internal stream state

Состояние внутреннего потока форматасохраняется до и восстанавливается после вывода аргумента; поэтому модификаторы не липкие и влияют только на аргумент, к которому они применяются.
Состояние по умолчанию для потоков, как указано в стандарте: точность 6, ширина 0, правильное выравнивание и десятичный флаг.

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

cout << format("%1% %2% %1%\n") % group(hex, showbase, 40) % 50; // prints "0x28 50 0x28\n"


При прохождении N предметов внутри «группы» увеличивается. Формат должен обрабатывать манипуляторы дифференцированно от обычного аргумента, и, таким образом, использование группы зависит от следующих ограничений:

  1. объект, подлежащий печати, должен быть передан в качестве последнего элемента в группе;
  2. Первые элементы N-1 рассматриваются как манипуляторы, и если они производят продукцию, она выбрасывается.

Такие манипуляторы передаются в потоки прямо перед следующим аргументом, при каждом происшествии. Обратите внимание, что параметры форматирования, указанные в строке формата, перекрываются модификаторами состояния потока, прошедшими таким образом. Например, в следующем коде манипуляторhexимеет приоритет надdспецификацией типа в строке формата, которая задает десятичный выход:

cout << format("%1$d %2% %1%\n") % group(hex, showbase, 40) % 50; 
// prints "0x28 50 0x28\n"

Alternatives

  • printfявляется классической альтернативой, которая не является безопасной по типу и не может быть распространена на определенные пользователем типы.
  • ofrstream.cc по дизайну Карла Нельсона был большим источником вдохновения для этого класса форматов.
  • Библиотека Джеймса Канзе имеет класс форматов (вsrcode/Extended/format), который выглядит очень хорошо отполированным. Его дизайн имеет общее с этим классом использование внутреннего потока для фактических преобразований, а также использование операторов для передачи аргументов. (но в его классе, как и в случае с rstream, используетсяоператор, а неоператор).
  • Библиотека Карла Нельсонабыла задумана как демонстрация альтернативных решений в дискуссиях по списку Бута для дизайна Boost.format.

Exceptions

Повышаю. Формат обеспечивает соблюдение ряда правил использования объектов формата. Формат-струна должна подчиняться синтаксису, описанному выше, пользователь должен предоставить точно нужное количество аргументов перед выводом в конечный пункт назначения, а при использовании change_item или bind_arg индекс элементов и аргументов не должен быть вне диапазона.
Когда формат обнаруживает, что одно из этих правил не выполняется, возникает соответствующее исключение, чтобы ошибки не оставались незамеченными и не устранялись.
Но пользователь может изменить это поведение в соответствии со своими потребностями и выбрать, какие типы ошибок могут вызвать исключения, используя следующие функции:

unsigned char exceptions(unsigned char newexcept); // query and set
unsigned char exceptions() const;                  // just query

Пользователь может вычислить аргумент, за исключением, объединив следующие атомы с помощью двоичной арифметики:

  • boost::io::bad_format_string_bitвыбирает ошибки из-за плохо сформированных строк формата.
  • boost::io::too_few_args_bitвыбирает ошибки из-за запроса результата сортировки до того, как все аргументы будут приняты.
  • boost::io::too_many_args_bitвыбирает ошибки из-за слишком большого количества аргументов.
  • boost::io::out_of_range_bitвыберите ошибки из-за индекса вне диапазона, предоставленного пользователем при вызовеchange_itemили других функций, принимающих индекс элемента (или индекс аргумента)
  • boost::io::all_error_bitsВсе ошибки
  • boost::io::no_error_bitsНе допускает ошибок.

Например, если вы не хотите, чтобы Boost.format обнаруживал плохое количество аргументов, вы можете определить конкретную функцию обертки для построения объектов формата с правильными настройками исключений:

boost::format  my_fmt(const std::string & f_string) {
    using namespace boost::io;
    format fmter(f_string);
    fmter.exceptions( all_error_bits ^ ( too_many_args_bit | too_few_args_bit )  );
    return fmter;
}
It is then allowed to give more arguments than needed (they are simply ignored) :
cout << my_fmt(" %1% %2% \n") % 1 % 2 % 3 % 4 % 5;
And if we ask for the result before all arguments are supplied, the corresponding part of the result is simply empty
cout << my_fmt(" _%2%_ _%1%_ \n") % 1 ;
// prints      " __ _1_ \n"

A Note about performance

Производительность импульса::формат для форматирования нескольких аргументов встроенного типа с переупорядочением можно сравнить с таковым у Posix-printf и эквивалентных операций ручного потока, чтобы дать меру понесенных накладных расходов. Результат может сильно зависеть от компилятора, реализации стандартной библиотеки и точного выбора строки формата и аргументов.

Поскольку реализация общих потоков в конечном итоге вызывает функции семейства printf для фактического форматирования чисел, в целом printf будет заметно быстрее, чем операции прямого потока. И из-за накладных расходов на переупорядочение (распределения для хранения частей строки, инициализации потока при каждом форматировании элемента, ..) операции прямого потока будут быстрее, чем импульс::формат (один кас ожидает соотношение от 2 до 5 или более)

При итерации форматирования является узким местом производительности, производительность может быть немного увеличена путем разбора строки формата в объект формата и копирования его при каждом форматировании следующим образом.

    const boost::format fmter(fstring);
    dest << boost::format(fmter) % arg1 % arg2 % arg3 ;

В качестве примера результатов работы автор измерил время выполнения итерационных форматов 4 различными методами.

  1. Posix Printf
  2. ручной вывод потока (в фиктивный потокnullStream, отправляющий байты в забвение)
  3. boost::формат, скопированный с объекта const, как показано выше
  4. Прямой импульс:: Использование формата

Тест был составлен с помощью g++-3.3.3 и были измерены следующие сроки (в секундах и соотношениях):

string     fstring="%3$0#6x %1$20.10E %2$g %3$0+5d \n";
double     arg1=45.23;
double     arg2=12.34;
int        arg3=23;
- release mode :
printf                 : 2.13
nullStream             : 3.43,  = 1.61033 * printf
boost::format copied   : 6.77,  = 3.1784  * printf ,  = 1.97376 * nullStream
boost::format straight :10.67,  = 5.00939 * printf ,  = 3.11079 * nullStream
- debug mode :
printf                 : 2.12
nullStream             : 3.69,  = 1.74057 * printf
boost::format copied   :10.02,  = 4.72642 * printf ,  = 2.71545 * nullStream
boost::format straight :17.03,  = 8.03302 * printf ,  = 4.61518 * nullStream

Class Interface Extract

namespace boost {
template<class charT, class Traits=std::char_traits<charT> > 
class basic_format 
{
public:
  typedef std::basic_string<charT, Traits> string_t;
  typedef typename string_t::size_type     size_type;
  basic_format(const charT* str);
  basic_format(const charT* str, const std::locale & loc);
  basic_format(const string_t& s);
  basic_format(const string_t& s, const std::locale & loc);
  basic_format& operator= (const basic_format& x);
  void clear(); // reset buffers
  basic_format& parse(const string_t&); // clears and parse a new format string
  string_t str() const;
  size_type size() const;
  // pass arguments through those operators :
  template<class T>  basic_format&   operator%(T& x);  
  template<class T>  basic_format&   operator%(const T& x);
  // dump buffers to ostream :
  friend std::basic_ostream<charT, Traits>& 
  operator<< <> ( std::basic_ostream<charT, Traits>& , basic_format& ); 
   // Choosing which errors will throw exceptions :
   unsigned char exceptions() const;
   unsigned char exceptions(unsigned char newexcept);
// ............  this is just an extract .......
}; // basic_format
typedef basic_format<char >          format;
typedef basic_format<wchar_t >      wformat;
// free function for ease of use :
template<class charT, class Traits> 
std::basic_string<charT,Traits>  str(const basic_format<charT,Traits>& f) {
      return f.str();
}
} // namespace boost

Rationale

Цель этого класса состоит в том, чтобы обеспечить лучший, C++, типобезопасный и расширяемыйprintfэквивалент для использования с потоками.

Precisely, format was designed to provide the following features :
  • поддержка позиционных аргументов (требуется для интернационализации);
  • Принять неограниченное количество аргументов.
  • Сделайте команды форматирования визуально естественными.
  • Поддерживать использование манипуляторов для изменения отображения аргумента. В дополнение к синтаксису формат-струна.
  • принимать любые типы переменных, полагаясь на потоки для фактического преобразования в строку. Это особенно касается определенных пользователем типов, для которых эффекты вариантов форматирования должны быть интуитивно естественными.
  • обеспечивают совместимость с типом, насколько это имеет смысл в безопасном и расширяемом по типу контексте.

В процессе проектирования возникло много проблем, и был сделан выбор, который может быть интуитивно неправильным. Но в каждом случае они были приняты понекоторым причинам.


Credits

Автором формата Boost является Самуэль Кремпп. Он использовал идеи из форматов Rüdiger Loos.hpp и Карла Нельсона.


Valid HTML 4.01 Transitional

Пересмотрено02 Декабря 200602 December, 2006[ORIG_END] -->

Авторское право и копия; 2002 Сэмюэл Кремпп

Распространяется по лицензии Boost Software License, версия 1.0. (См. сопроводительный файлLICENSE_1_0.txtили копию на) http://www.boost.org/LICENSE_1_0.txt)

Статья The Boost Format library раздела может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 02:13:26/0.015023946762085/1