From dba4d7ee04e68f9f529c0b8e352bf4f04ed12955 Mon Sep 17 00:00:00 2001 From: "Leonov Artur (Depish)" Date: Sat, 25 Oct 2025 16:10:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B5=D1=82=D0=BE=D1=87=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- boost/1.89.0/design_discussion.md | 77 +++++ boost/1.89.0/how_to.md | 333 ++++++++++++++++++++++ boost/1.89.0/index.md | 7 +- boost/1.89.0/library_overview.md | 451 ++++++++++++++++++++++++++++++ boost/1.89.0/tutorial.md | 118 ++++++++ 5 files changed, 985 insertions(+), 1 deletion(-) create mode 100644 boost/1.89.0/design_discussion.md create mode 100644 boost/1.89.0/how_to.md create mode 100644 boost/1.89.0/library_overview.md create mode 100644 boost/1.89.0/tutorial.md diff --git a/boost/1.89.0/design_discussion.md b/boost/1.89.0/design_discussion.md new file mode 100644 index 0000000..1155c1a --- /dev/null +++ b/boost/1.89.0/design_discussion.md @@ -0,0 +1,77 @@ +## Обсуждение дизайна библиотеки + +### Поддержка Unicode + +**Unicode-поддержка** в библиотеке означает: +* Возможность парсинга как char*, так и wchar_t* +* Возможность указания типа обработки для каждой опции (ASCII или Unicode) +* Гарантии корректной конвертации данных + +### Основные гарантии библиотеки + +* ASCII-вход передается в ASCII-значение без изменений +* Unicode-вход передается в Unicode-значение без изменений +* При несовпадении типов происходит автоматическая конвертация через codecvt + +### Особенности реализации + +**Смешанная поддержка** ASCII и Unicode: +* Возможность использования обоих типов опций одновременно +* Отсутствие необходимости писать дополнительный код для Unicode +* Совместимость с существующими библиотеками + +### Проблемы реализации + +**Основные сложности**: +* Сравнение Unicode-строк +* Интернационализация имен опций +* Необходимость дополнительных настроек для корректной работы + +### Подход к реализации + +**Варианты реализации**: +1. Шаблонное решение с std::basic_string +2. Внутренняя кодировка с конвертацией на границах + +**Выбранный подход**: +* Использование внутренней кодировки UTF-8 +* Конвертация только при необходимости +* Минимизация накладных расходов + +### Компоненты системы + +**Парсеры**: +* Работа с входными строками +* Конвертация в internal encoding +* Хранение результатов в parsed_options + +**Описания опций**: +* Поддержка смешанных типов +* Дополнительная информация о кодировке +* Гибкая обработка значений + +**Хранение данных**: +* Конвертация при сохранении +* Информирование о типе кодировки +* Корректная работа с разными типами + +### Выбор внутренней кодировки + +**Критерии выбора**: +* Скорость обработки +* Затраты памяти +* Размер кода + +**Принятое решение**: UTF-8 как внутренняя кодировка из-за: +* Универсальности +* Эффективности для ASCII-данных +* Простоты интеграции с существующими компонентами + +### Особые случаи + +**Важные моменты**: +* Предполагается ASCII-кодировка для символьных литералов +* Учет возможных проблем с комбинирующими символами +* Практическая нерелевантность проблем в большинстве случаев + +Такой подход обеспечивает баланс между функциональностью, производительностью и простотой использования библиотеки. \ No newline at end of file diff --git a/boost/1.89.0/how_to.md b/boost/1.89.0/how_to.md new file mode 100644 index 0000000..2015c93 --- /dev/null +++ b/boost/1.89.0/how_to.md @@ -0,0 +1,333 @@ +## Нестандартные случаи использования библиотеки + +### Нестандартный синтаксис + +Иногда требуется поддержка нестандартного синтаксиса командных строк. Например, как в компиляторе gcc с опциями `-frtti` и `-fno-rtti`. + +Для таких случаев библиотека позволяет предоставить дополнительный парсер — функцию, которая вызывается для каждого элемента командной строки. + +Пример реализации: +```cpp +pair reg_foo(const string& s) { + if (s.find("-f") == 0) { + if (s.substr(2, 3) == "no-") + return make_pair(s.substr(5), string("false")); + else + return make_pair(s.substr(2), string("true")); + } else { + return make_pair(string(), string()); + } +} +``` + +Использование дополнительного парсера: +```cpp +store(command_line_parser(ac, av) + .options(desc) + .extra_parser(reg_foo) + .run(), vm); +``` + +### Файлы ответов (Response Files) + +Для обхода ограничений длины командной строки используются файлы ответов. + +Шаги реализации: + +1. Определение опции для файла ответов: +```cpp +("response-file", value(), "can be specified with '@name', too") +``` + +2. Дополнительный парсер для синтаксиса `@file`: +```cpp +pair at_option_parser(string const&s) { + if ('@' == s[0]) + return make_pair(string("response-file"), s.substr(1)); + else + return make_pair(string(), string()); +} +``` + +3. Обработка найденного файла ответов: +```cpp +if (vm.count("response-file")) { + ifstream ifs(vm["response-file"].as().c_str()); + if (!ifs) { + cout << "Could not open the response file\n"; + return 1; + } + + stringstream ss; + ss << ifs.rdbuf(); + + char_separator sep(" \n\r"); + string ResponsefileContents(ss.str()); + tokenizer> tok(ResponsefileContents, sep); + + vector args; + copy(tok.begin(), tok.end(), back_inserter(args)); + + store(command_line_parser(args).options(desc).run(), vm); +} +``` + +### Другие возможности + +* **Winmain Command Line** — поддержка специфичного синтаксиса Windows +* **Группы опций и скрытые опции** — организация опций в логические группы +* **Пользовательские валидаторы** — создание собственных правил проверки значений +* **Поддержка Unicode** — работа с Unicode-строками +* **Неизвестные опции** — возможность разрешать неизвестные опции +* **Проверка наличия опций** — механизмы проверки присутствия опций + +Эти возможности позволяют гибко настраивать поведение библиотеки под конкретные требования проекта. + + +## Работа с командной строкой в Windows + +### Особенности Winmain + +В Windows GUI-приложения получают командную строку как единую строку, а не как массив элементов. Для решения этой проблемы библиотека предоставляет функцию **split_winmain**. + +Пример использования: +```cpp +vector args = split_winmain(lpCmdLine); +store(command_line_parser(args).options(desc).run(), vm); +``` + +Функция **split_winmain** имеет перегрузку для строк **wchar_t**, что позволяет использовать её в Unicode-приложениях. + +## Группы опций и скрытые опции + +### Проблемы единого описания опций + +При использовании единого экземпляра **options_description** возникают сложности: +* Некоторые опции имеют смысл только для определённых источников +* Требуется структурированная справка +* Некоторые опции не должны отображаться в справке + +### Решение через группы опций + +Библиотека позволяет создавать несколько экземпляров **options_description** и объединять их по необходимости. + +Пример группировки: + +```cpp +// Общая группа опций +options_description general("Общие опции"); +general.add_options() + ("help", "показать справку") + ("help-module", value(), "показать справку по модулю") + ("version", "показать версию"); + +// Группа опций GUI +options_description gui("Опции GUI"); +gui.add_options() + ("display", value(), "используемый дисплей"); + +// Группа опций бэкенда +options_description backend("Опции бэкенда"); +backend.add_options() + ("num-threads", value(), "начальное число потоков"); +``` + +### Объединение групп + +Создаём два объединения: +* Полное для парсинга +* Видимое для справки + +```cpp +// Все опции для парсинга +options_description all("Разрешённые опции"); +all.add(general).add(gui).add(backend); + +// Видимые опции для справки +options_description visible("Разрешённые опции"); +visible.add(general).add(gui); +``` + +### Обработка опций + +```cpp +variables_map vm; +store(parse_command_line(ac, av, all), vm); + +if (vm.count("help")) { + cout << visible; + return 0; +} + +if (vm.count("help-module")) { + const string& s = vm["help-module"].as(); + if (s == "gui") { + cout << gui; + } else if (s == "backend") { + cout << backend; + } else { + cout << "Неизвестный модуль '" << s << "'\n"; + return 1; + } + return 0; +} +``` + +Такой подход позволяет: +* Структурировать опции по группам +* Контролировать видимость опций в справке +* Гибко настраивать поведение программы + + +## Пользовательские валидаторы + +### Настройка конвертации значений + +По умолчанию конвертация значений опций выполняется через iostreams. Библиотека позволяет настроить собственную конвертацию для конкретных классов. + +Пример создания пользовательского валидатора: + +```cpp +struct magic_number { +public: + magic_number(int n) : n(n) {} + int n; +}; + +void validate(boost::any& v, + const std::vector& values, + magic_number* target_type, int) +{ + static regex r("\\d\\d\\d-(\\d\\d\\d)"); + using namespace boost::program_options; + + // Проверка на множественные присваивания + validators::check_first_occurrence(v); + + // Получение единственной строки + const string& s = validators::get_single_string(values); + + // Проверка через регулярное выражение + smatch match; + if (regex_match(s, match, r)) { + v = any(magic_number(lexical_cast(match[1]))); + } else { + throw validation_error(validation_error::invalid_option_value); + } +} +``` + +Параметры функции валидации: +* **v** — хранилище для значения +* **values** — список строк +* **target_type** — указатель на целевой тип +* Дополнительный параметр для совместимости с компиляторами + +### Поддержка Unicode + +Для работы с Unicode необходимо: +* Использовать Unicode-совместимые парсеры +* Указывать поддержку Unicode для нужных опций + +Особенности работы: +* Большинство парсеров имеют Unicode-версии +* Для создания Unicode-опций используется **wvalue** вместо **value** +* Автоматическое преобразование кодировок между Unicode и локальными + +### Настройка локализаций + +Для корректной работы с Unicode: +```cpp +locale::global(locale("")); // Настройка конвертации согласно локали пользователя +``` + +### Тестирование поддержки локализаций + +Проверка включает: +1. Сборка теста **test_convert** +2. Установка не-ASCII локали: + ```bash + export LC_CTYPE=ru_RU.KOI8-R + ``` +3. Запуск теста с не-ASCII строкой + +При успешной работе вы увидите список Unicode-кодов, что подтверждает корректную поддержку локализаций. + +Такой подход позволяет: +* Настраивать собственную логику валидации +* Работать с Unicode-данными +* Обеспечивать корректную конвертацию кодировок + +## Разрешение неизвестных опций + +### Стандартное поведение + +По умолчанию библиотека генерирует исключение при обнаружении неизвестных опций. Однако это поведение можно изменить. + +### Разрешение неизвестных опций + +Для разрешения неизвестных опций: +1. Используйте **basic_command_line_parser** вместо **parse_command_line** +2. Вызовите метод **allow_unregistered** + +Пример: +```cpp +parsed_options parsed = command_line_parser(argc, argv) + .options(desc) + .allow_unregistered() + .run(); +``` + +При обнаружении неизвестной опции создается объект **basic_option** с полями: +* **string_key** — имя опции +* **value** — значение опции +* **unregistered** — флаг неизвестной опции +* **original_tokens** — исходные токены + +### Передача неизвестных опций + +Для сбора неизвестных опций используйте функцию **collect_unrecognized**: +```cpp +vector to_pass_further = collect_unrecognized( + parsed.options, + include_positional +); +``` + +## Проверка наличия опций + +### Традиционный подход + +Ранее проверка осуществлялась через метод **count**: +```cpp +if (vm.count("compression")) { + cout << "Уровень сжатия установлен: " << vm["compression"].as() << endl; +} +``` + +### Улучшенный подход с boost::optional + +Использование **boost::optional** позволяет: +* Автоматически инициализировать переменную при наличии опции +* Упростить проверку наличия опции + +Пример: +```cpp +boost::optional compression; +desc.add_options() + ("compression", po::value(&compression), "уровень сжатия"); + +// После парсинга и уведомления +if (compression) { + cout << "Уровень сжатия установлен: " << *compression << endl; +} else { + cout << "Уровень сжатия не установлен" << endl; +} +``` + +Преимущества подхода с **boost::optional**: +* Меньше вероятность ошибок при переименовании опций +* Более чистый код +* Автоматическая обработка наличия значения + +Такой подход рекомендуется использовать для проверки наличия опций в программе. \ No newline at end of file diff --git a/boost/1.89.0/index.md b/boost/1.89.0/index.md index 6a15792..bbaad0e 100644 --- a/boost/1.89.0/index.md +++ b/boost/1.89.0/index.md @@ -1,2 +1,7 @@ +# Оглавление -- [Introducion](introduction.md) \ No newline at end of file +- [Введение](introduction.md) +- [Туториал](tutorial.md) +- [Обзор библиотеки](library_overview.md) +- [How To](how_to.md) +- [Обсуждение дизайна](design_discussion.md) diff --git a/boost/1.89.0/library_overview.md b/boost/1.89.0/library_overview.md new file mode 100644 index 0000000..6c5d10c --- /dev/null +++ b/boost/1.89.0/library_overview.md @@ -0,0 +1,451 @@ +## Общая архитектура библиотеки program_options + +### Основные компоненты библиотеки + +Библиотека состоит из трёх главных компонентов: + +* **Компонент описания опций** — определяет допустимые параметры и действия с их значениями +* **Компонент парсеров** — использует эту информацию для поиска имён параметров и их значений в источниках ввода +* **Компонент хранения** — предоставляет интерфейс для доступа к значениям параметров и преобразует строковые представления в нужные типы C++ + +### Ключевые классы и функции + +* Класс **options_description** относится к компоненту описания опций +* Функция **parse_command_line** является частью компонента парсеров +* Класс **variables_map** принадлежит компоненту хранения + +### Взаимодействие компонентов + +В предыдущих примерах мы видели, как эти компоненты используются в функции main для парсинга командной строки и конфигурационных файлов. Рассмотрим теперь особенности работы вне функции main. + +### Архитектура программы + +Для частей программы, находящихся вне main, наиболее важен **компонент хранения**. Он предоставляет класс, хранящий все значения параметров, который можно свободно передавать между модулями программы. + +Важные особенности: +* Остальные компоненты используются только там, где выполняется парсинг +* Отдельные модули программы могут описывать свои параметры и передавать их в основной модуль +* Основной модуль может объединять все описания параметров +* Такой подход особенно полезен при большом количестве параметров + +### Рекомендации по использованию + +При разработке крупных приложений рекомендуется: +* Централизовать описание параметров в одном месте +* Использовать модульный подход при большом количестве опций +* Передавать объект хранения между компонентами программы +* Обеспечивать корректную обработку параметров во всех модулях + + +## Компонент описания опций + +### Основные классы компонента + +Компонент описания опций включает три ключевых класса: + +* **option_description** — содержит имя опции, описание и указатель на value_semantic +* **value_semantic** — знает тип значения опции, может парсить значение, применять значение по умолчанию +* **options_description** — контейнер для экземпляров option_description + +### Синтаксическое и семантическое описание + +#### Синтаксическая информация +Включает: +* Имя опции +* Количество токенов для указания значения +* Используется парсерами для группировки токенов в пары (имя, значение) + +#### Семантическая информация +Отвечает за: +* Преобразование значений в типы C++ +* Валидацию данных +* Применение значений по умолчанию + +### Практическое применение + +Пример объявления опций: +```cpp +options_description desc; +desc.add_options() + ("help", "показать справку") + ("optimization", value()->default_value(10), "уровень оптимизации") + ; +``` + +### Механизм работы + +* Функция **value** создаёт экземпляр класса **typed_value** +* **typed_value** — производный класс от **value_semantic** +* Содержит код для парсинга значений определённого типа +* Поддерживает методы для указания дополнительной информации + +### Дополнительные возможности + +Библиотека предоставляет: +* Функцию **bool_switch** для булевых значений +* Возможность создания пользовательских подклассов **value_semantic** + +### Важные аспекты проектирования + +Разделение на синтаксический и семантический уровни: +* Парсеры работают только с синтаксическим уровнем +* Ограничивает использование чрезмерно сложных структур +* Пример проблемы: +```bash +calc --expression=1 + 2/3 # сложно парсить без контекста +``` +* Решённая версия: +```bash +calc --expression="1 + 2/3" # синтаксис ясен +``` + +Такое разделение является ключевым элементом дизайна библиотеки, обеспечивая чёткое разделение ответственности между компонентами. + + +## Синтаксическая информация опций + +### Основные компоненты + +Синтаксическая информация предоставляется классами **boost::program_options::options_description** и методами **boost::program_options::value_semantic**. Она включает: + +* **Имя опции** — используется для идентификации внутри программы +* **Описание опции** — отображается пользователю +* **Количество токенов** — определяет, сколько элементов может содержать значение опции при парсинге + +### Примеры использования + +Рассмотрим практический пример объявления опций: + +```cpp +options_description desc; +desc.add_options() + ("help", "показать справочное сообщение") + ("compression", value(), "уровень сжатия") + ("verbose", value()->implicit_value("0"), "уровень детализации") + ("email", value()->multitoken(), "email для отправки") +; +``` + +Особенности каждой опции: +* Первая опция (`help`) не требует значения +* Вторая опция (`compression`) требует ровно один токен значения +* Третья опция (`verbose`) может принимать либо один токен, либо не принимать значение вообще +* Четвёртая опция (`email`) может принимать несколько токенов + +### Пример командной строки + +Допустимый вариант использования опций: + +```bash +test --help --compression 10 --verbose --email beadle@mars beadle2@mars +``` + +### Важные характеристики + +* **Неявные значения** (implicit_value) позволяют опции иметь значение по умолчанию при отсутствии явного указания +* **Многокомпонентные значения** (multitoken) позволяют опции принимать несколько токенов +* Каждая опция может иметь собственное правило обработки значений + +Такой подход обеспечивает гибкость при определении правил обработки параметров командной строки и конфигурационных файлов. + +## Форматирование описаний опций + +### Базовое форматирование + +Описания опций могут быть достаточно объёмными, особенно когда требуется документировать несколько значений. Библиотека предоставляет простые механизмы форматирования. + +### Структура описания + +* Описание состоит из одного или нескольких параграфов, разделённых символом новой строки (`\n`) +* При выводе библиотека автоматически вычисляет отступы для описания опции +* Каждый параграф выводится как отдельная строка с рассчитанным отступом +* Если параграф не помещается в одну строку, он переносится на несколько строк с одинаковым отступом + +### Управление отступами + +#### Базовый отступ + +Можно задать дополнительный отступ для первой строки, добавив пробелы в начале параграфа: + +```cpp +options.add_options() + ("help", " Подробное описание опции, которое может быть очень длинным и занимать несколько строк") +; +``` + +Результат будет выглядеть так: +``` +--help Подробное описание опции, которое может быть + очень длинным и занимать несколько строк +``` + +### Расширенное форматирование + +Для более сложного форматирования можно использовать символ табуляции (`\t`): + +```cpp +options.add_options() + ("well_formated", "Описание опции:\n" + "\n" + "Значения:\n" + " Значение1:\tОписание первого значения, которое может быть длинным\n" + " Значение2:\tОписание второго значения\n" + "\n" + " Этот параграф имеет отступ только для первой строки"); +``` + +Результат: +``` +--well_formated Описание опции: + + Значения: + Значение1: Описание первого значения, которое может быть + длинным + Значение2: Описание второго значения + + Этот параграф имеет отступ только для первой строки +``` + +### Важные ограничения + +* Символ табуляции удаляется перед выводом +* Разрешён только один символ табуляции на параграф +* При нарушении этого правила выбрасывается исключение типа `program_options::error` +* Табуляция игнорируется, если: + * Она находится не в первой строке параграфа + * Она расположена в последней возможной позиции первой строки + + +## Семантическая информация и парсеры + +### Семантическая информация + +Семантическая информация полностью предоставляется классом **boost::program_options::value_semantic**. Рассмотрим пример: + +```cpp +options_description desc; +desc.add_options() + ("compression", value()->default_value(10), "уровень сжатия") + ("email", value>() + ->composing()->notifier(&your_function), "email") + ; +``` + +Этот код определяет: +* Значение по умолчанию для первой опции — 10 +* Вторая опция может появляться несколько раз, и все значения будут объединены +* После парсинга будет вызвана функция `your_function` с значением опции "email" + +### Позиционные опции + +**Позиционные опции** — это элементы командной строки без явного указания имени опции. Например: +```bash +archiver --compression=9 /etc/passwd +``` + +Здесь `/etc/passwd` — позиционная опция. + +Для обработки таких опций используется класс **positional_options_description**: + +```cpp +positional_options_description pd; +pd.add("input-file", 1); // Первая позиционная опция будет иметь имя "input-file" +``` + +Можно задать несколько позиционных опций: +```cpp +positional_options_description pd; +pd.add("output-file", 2).add("input-file", -1); +``` + +В этом примере: +* Первые две позиционные опции получат имя "output-file" +* Все последующие — имя "input-file" + +**Важное замечание**: класс **positional_options_description** только определяет соответствие позиции имени, само имя должно быть зарегистрировано в экземпляре **options_description**. + +### Компонент парсеров + +**Компонент парсеров** выполняет следующие функции: +* Разбивает входные данные на пары (имя, значение) +* Проверяет, известны ли опции +* Определяет способ указания значений + +Процесс парсинга: +1. Парсер ищет возможные опции +2. Сверяется с описанием опций +3. Определяет, известно ли имя опции +4. Использует **value_semantic** для обработки значений + +### Особенности парсинга + +Три важных исключения из стандартной модели: + +1. **Короткие имена опций**: + * Можно использовать сокращённые имена + * Поддерживается автоматическое определение по префиксам + +2. **Многокомпонентные значения**: + * Опция может принимать несколько токенов + * Требует явного включения + +3. **Позиционные опции**: + * Механизм автоматического определения имён + * Гибкая настройка через **positional_options_description** + +### Использование парсеров + +Для запуска парсера обычно вызывается функция с параметрами: +* Описание опций +* Источник данных (командная строка, конфигурационный файл) + +Результаты парсинга возвращаются в виде объекта класса **parsed_options**, который передаётся компоненту хранения. + + +## Компонент хранения + +### Основные функции + +Компонент хранения отвечает за: +* Хранение конечных значений опций в специальном классе и обычных переменных +* Управление приоритетами между различными источниками +* Вызов пользовательских функций уведомления с финальными значениями опций + +### Пример использования + +```cpp +variables_map vm; +store(parse_command_line(argc, argv, desc), vm); +store(parse_config_file("example.cfg", desc), vm); +notify(vm); +``` + +### Особенности работы + +* Класс **variables_map** используется для хранения значений опций +* Функция **store** добавляет значения из различных источников +* Функция **notify** запускает пользовательские обработчики и сохраняет значения в обычные переменные +* Приоритет определяется порядком обработки: если значение уже установлено, оно не перезаписывается + +### Важное предупреждение + +**Не забудьте** вызвать функцию **notify** после сохранения всех проанализированных значений! + +## Парсеры конфигурационных файлов + +### Синтаксис конфигурационных файлов + +Файлы конфигурации имеют простой INI-подобный формат: + +* Строка вида `name=value` задаёт значение опции +* Секция начинается со строки `[section name]` +* Символ `#` начинает комментарий до конца строки + +### Иерархия опций + +Имена опций относительны к именам секций. Например: + +```ini +[gui.accessibility] +visual_bell=yes +``` + +эквивалентно: + +```ini +gui.accessibility.visual_bell=yes +``` + +### Пример описания опции + +```cpp +options_description desc; +desc.add_options() + ("gui.accessibility.visual_bell", value(), "визуальный звонок") + ; +``` + +### Парсер переменных окружения + +Библиотека также поддерживает парсинг переменных окружения, что позволяет: +* Использовать значения из окружения системы +* Объединять их с другими источниками конфигурации +* Управлять поведением программы через системные переменные + +Такой подход обеспечивает гибкую систему конфигурации приложения с возможностью комбинирования различных источников настроек. + + +## Парсер переменных окружения + +### Что такое переменные окружения + +**Переменные окружения** — это строковые переменные, доступные всем программам через функцию `getenv` стандартной библиотеки C. Их можно установить: +* Для всей системы +* Для конкретного пользователя +* Через командную строку + +### Использование парсера + +Функция **parse_environment** позволяет парсить переменные окружения. У неё есть несколько перегруженных версий. Первый параметр — экземпляр **options_description**, второй определяет, какие переменные обрабатывать. + +### Соглашения об именовании + +Для избежания конфликтов имён рекомендуется: +* Использовать уникальный префикс для переменных окружения +* Использовать верхний регистр для имён переменных +* Преобразовывать имена опций в нижний регистр + +Пример: +* Опция: `proxy` +* Переменная окружения: `BOOST_PROXY` + +### Настройка парсинга + +При вызове **parse_environment** можно указать: +* Префикс для фильтрации переменных +* Функцию преобразования имён (принимает `std::string` и возвращает `std::string`) + +### Преобразование типов + +Все значения из командной строки, переменных окружения и конфигурационных файлов изначально являются строками. Библиотека автоматически преобразует их в нужные типы. + +#### Числовые типы + +Преобразование выполняется через **lexical_cast**: +* Поддерживаются целые числа: `41`, `-42` +* Поддерживаются числа с плавающей точкой: `51.1`, `-52.1`, `53.1234567890` +* Поддерживаются экспоненциальные записи: `57.1e5`, `58.1E5` + +#### Булевы значения + +Есть два способа работы с булевыми значениями: + +1. Через явное указание: +```bash +example --my-option=true +``` + +2. Через переключатель: +```bash +example --other-switch +``` + +Значения, интерпретируемые как true: +* `true` +* `yes` +* `on` +* `1` + +Значения, интерпретируемые как false: +* `false` +* `no` +* `off` +* `0` + +В конфигурационных файлах опция с именем и знаком равенства без значения также интерпретируется как true. + +### Важные замечания + +* Шестнадцатеричные, восьмеричные и двоичные представления не поддерживаются +* Преобразование типов выполняется автоматически при обращении к значениям +* Рекомендуется явно указывать ожидаемый тип при описании опций \ No newline at end of file diff --git a/boost/1.89.0/tutorial.md b/boost/1.89.0/tutorial.md new file mode 100644 index 0000000..5b5c268 --- /dev/null +++ b/boost/1.89.0/tutorial.md @@ -0,0 +1,118 @@ +## Основные сценарии использования библиотеки program_options + +### Начало работы + +В этом разделе мы рассмотрим простейший пример использования библиотеки. Предполагается, что действует следующий алиас пространства имён: + +```cpp +namespace po = boost::program_options; +``` + +#### Пример базового использования + +Простейший пример, обрабатывающий два параметра: + +```cpp +// Объявление поддерживаемых параметров +po::options_description desc("Допустимые параметры"); +desc.add_options() + ("help", "показать справочную информацию") + ("compression", po::value(), "установить уровень сжатия"); + +po::variables_map vm; +po::store(po::parse_command_line(ac, av, desc), vm); +po::notify(vm); + +if (vm.count("help")) { + cout << desc << "\n"; + return 1; +} + +if (vm.count("compression")) { + cout << "Уровень сжатия установлен на " + << vm["compression"].as() << ".\n"; +} else { + cout << "Уровень сжатия не установлен.\n"; +} +``` + +### Детали работы с параметрами + +#### Типы и свойства параметров + +Рассмотрим более сложный пример на основе компилятора: + +```cpp +int opt; +po::options_description desc("Допустимые параметры"); +desc.add_options() + ("help", "показать справочную информацию") + ("optimization", po::value(&opt)->default_value(10), "уровень оптимизации") + ("include-path,I", po::value>(), "путь включения") + ("input-file", po::value>(), "входной файл"); +``` + +Особенности этого примера: +* Параметр `optimization` имеет значение по умолчанию 10 +* Параметр `include-path` поддерживает короткое имя `-I` +* Векторные типы позволяют указывать параметр несколько раз + +#### Позиционные параметры + +```cpp +po::positional_options_description p; +p.add("input-file", -1); + +po::variables_map vm; +po::store(po::command_line_parser(ac, av) + .options(desc).positional(p).run(), vm); +po::notify(vm); +``` + +### Использование нескольких источников + +#### Группировка параметров + +```cpp +// Общие параметры командной строки +po::options_description generic("Общие параметры"); +generic.add_options() + ("version,v", "показать версию") + ("help", "показать справку"); + +// Параметры конфигурации +po::options_description config("Конфигурация"); +config.add_options() + ("optimization", po::value(&opt)->default_value(10), "уровень оптимизации") + ("include-path,I", po::value>()->composing(), "путь включения"); + +// Скрытые параметры +po::options_description hidden("Скрытые параметры"); +hidden.add_options() + ("input-file", po::value>(), "входной файл"); +``` + +Пример использования: +```bash +$ bin/gcc/debug/multiple_sources +Пути включения: /opt +Уровень оптимизации: 1 + +$ bin/gcc/debug/multiple_sources --help +Допустимые параметры: + +Общие параметры: + -v [ --версия ] : показать версию + --help : показать справку + +Конфигурация: + --оптимизация n : уровень оптимизации + -I [ --путь-включения ] путь : путь включения + +$ bin/gcc/debug/multiple_sources --оптимизация=4 -I foo a.cpp b.cpp +Пути включения: foo /opt +Входные файлы: a.cpp b.cpp +Уровень оптимизации: 4 +``` + +В этом примере значения из конфигурационного файла и командной строки корректно объединяются, при этом значения из командной строки имеют приоритет. \ No newline at end of file