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

Tutorial

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 27. Boost.Program_options

BoostC++ Libraries

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

PrevUpHomeNext

Tutorial

В этом разделе мы рассмотрим наиболее распространенные сценарии использования библиотеки Program_options, начиная с самого простого. Примеры показывают только интересные части кода, но полные программы можно найти в каталоге «BOOST_ROOT/libs/program_options/example». На всех примерах мы предположим, что действует следующий псевдоним пространства имен:

namespace po = boost::program_options;

Getting Started

Первый пример самый простой: он обрабатывает только два варианта. Вот исходный код (полная программа находится в "пример/первый.cpp"):

// Declare the supported options.
po::options_description desc("Allowed options");
desc.add_options()
    ("help", "produce help message")
    ("compression", po::value<int>(), "set compression level")
;
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 << "Compression level was set to " 
 << vm["compression"].as<int>() << ".\n";
} else {
    cout << "Compression level was not set.\n";
}

Мы начинаем с объявления всех разрешенных вариантов с использованием класса<options_description>. Метод<add_options>этого класса возвращает специальный прокси-объект, который определяет<operator()>. Звонки этому оператору фактически объявляют опции. Параметрами являются имя опции, информация о значении и описание опции. В этом примере первый вариант не имеет значения, а второй имеет значение типа<int>.

После этого объявляется объект класса<variables_map>. Этот класс предназначен для хранения значений опционов и может хранить значения произвольных типов. Затем вызовы<store>,<parse_command_line>и<notify>функций заставляют<vm>содержать все опции, найденные в командной строке.

И теперь, наконец, мы можем использовать варианты, как нам нравится. Класс<variables_map>может использоваться так же, как<std::map>, за исключением того, что значения, хранящиеся там, должны быть извлечены с помощью метода<as>, показанного выше. (Если тип, указанный в вызове к<as>способу, отличается от фактически сохраненного типа, забрасывается исключение.)

Сейчас самое время попробовать составить код самостоятельно, но если вы еще не готовы, вот пример сессии:

$ bin/gcc/debug/first
Compression level was not set.
$ bin/gcc/debug/first --help
Allowed options:
  --help                 : produce help message
  --compression arg      : set compression level
$ bin/gcc/debug/first --compression 10
Compression level was set to 10.
    

Option Details

Значение опциона, безусловно, может иметь другие типы, чем<int>, и может иметь другие интересные свойства, которые мы обсудим прямо сейчас. Полную версию кода можно найти в<example/options_description.cpp>.

Представьте, что мы пишем компилятор. Он должен занимать уровень оптимизации, включать в себя несколько путей и несколько входных файлов и выполнять некоторые интересные работы. Давайте опишем варианты:

int opt;
po::options_description desc("Allowed options");
desc.add_options()
    ("help", "produce help message")
    ("optimization", po::value<int>(&opt)->default_value(10), 
  "optimization level")
    ("include-path,I", po::value< vector<string> >(), 
  "include path")
    ("input-file", po::value< vector<string> >(), "input file")
;

Вариант<"help">должен быть знаком из предыдущего примера. Это хорошая идея, чтобы иметь этот вариант во всех случаях.

Вариант<"optimization">показывает две новые функции. Во-первых, мы указываем адрес переменной<&opt>. После хранения значений эта переменная будет иметь значение опции. Во-вторых, мы указываем значение 10 по умолчанию, которое будет использоваться, если пользователь не указал значение.

Вариант<"include-path">является примером единственного случая, когда интерфейс класса<options_description>обслуживает только один источник — командную строку. Пользователи обычно любят использовать короткие имена опций для общих опций, а имя «include-path, I» указывает, что короткое имя опции — «I». Таким образом, можно использовать как «--включить-путь», так и «-я».

Отметим также, что тип<"include-path">опцииstd::vector. Библиотека обеспечивает специальную поддержку векторов — можно будет несколько раз указать опцию, и все заданные значения будут собраны в один вектор.

Опция «вход-файл» определяет список файлов для обработки. Это нормально для начала, но, конечно, написать что-то вроде:

compiler --input-file=a.cpp
    

Это немного нестандартно по сравнению с

compiler a.cpp
    

Мы обсудим это через минуту.

Токены командной строки, которые не имеют названия опции, как указано выше, называются этой библиотекой «позиционными опциями». С ними тоже можно справиться. С небольшой помощью пользователя библиотека может решить, что «a.cpp» на самом деле означает то же самое, что «--input-file=a.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);
    

Первые две строки говорят, что все позиционные опции должны быть переведены в опции «вход-файл». Также обратите внимание, что мы используем класс<command_line_parser>для разбора командной строки, а не функцию<parse_command_line>. Последний является удобной оберткой для простых случаев, но сейчас нужно передать дополнительную информацию.

К настоящему времени все варианты описаны и разобраны. Мы избавим себя от проблем с реализацией остальной логики компилятора и распечатаем только опции:

if (vm.count("include-path"))
{
    cout << "Include paths are: " 
         << vm["include-path"].as< vector<string> >() << "\n";
}
if (vm.count("input-file"))
{
    cout << "Input files are: " 
         << vm["input-file"].as< vector<string> >() << "\n";
}
cout << "Optimization level is " << opt << "\n";                

Вот пример сессии:

$ bin/gcc/debug/options_description --help
Usage: options_description [options]
Allowed options:
  --help                 : produce help message
  --optimization arg     : optimization level
  -I [ --include-path ] arg : include path
  --input-file arg       : input file
$ bin/gcc/debug/options_description
Optimization level is 10
$ bin/gcc/debug/options_description --optimization 4 -I foo a.cpp
Include paths are: foo
Input files are: a.cpp
Optimization level is 4

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

Multiple Sources

Вполне вероятно, что указание всех опций нашему компилятору в командной строке будет раздражать пользователей. Что делать, если пользователь устанавливает новую библиотеку и хочет всегда проходить дополнительный элемент командной строки? Что, если он сделал выбор, который должен быть применен на каждом бегу? Желательно создать файл конфигурации с общими настройками, который будет использоваться вместе с командной строкой.

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

Теперь посмотрим код. Полная программа находится в "примеры/multiple_sources.cpp". Определение опции имеет две интересные детали. Во-первых, мы объявляем несколько экземпляров класса<options_description>. Причина в том, что в целом не все варианты одинаковы. Некоторые опции, такие как «вход-файл» выше, не должны отображаться в автоматическом сообщении справки. Некоторые опции имеют смысл только в файле конфигурирования. Наконец, приятно иметь некоторую структуру в сообщении о помощи, а не просто длинный список вариантов. Объявим несколько групп вариантов:

// Declare a group of options that will be 
// allowed only on command line
po::options_description generic("Generic options");
generic.add_options()
    ("version,v", "print version string")
    ("help", "produce help message")    
    ;
    
// Declare a group of options that will be 
// allowed both on command line and in
// config file
po::options_description config("Configuration");
config.add_options()
    ("optimization", po::value<int>(&opt)->default_value(10), 
          "optimization level")
    ("include-path,I", 
         po::value< vector<string> >()->composing(), 
         "include path")
    ;
// Hidden options, will be allowed both on command line and
// in config file, but will not be shown to the user.
po::options_description hidden("Hidden options");
hidden.add_options()
    ("input-file", po::value< vector<string> >(), "input file")
    ;        

Обратите внимание на призыв к методу<composing>в объявлении опции «включающий путь». Это говорит библиотеке, что ценности из разных источников должны быть составлены вместе, как мы скоро увидим.

Способ<add>класса<options_description>может быть использован для дальнейшей группировки вариантов:

po::options_description cmdline_options;
cmdline_options.add(generic).add(config).add(hidden);
po::options_description config_file_options;
config_file_options.add(config).add(hidden);
po::options_description visible("Allowed options");
visible.add(generic).add(config);
      

Разбор и хранение значений следует обычной схеме, за исключением того, что мы дополнительно называем<parse_config_file>и называем функцию<store>дважды. Но что происходит, если одно и то же значение указано как в командной строке, так и в файле конфигурирования? Обычно значение, сохраненное первым, является предпочтительным. Вот что происходит с опцией «оптимизация». Для «составляющих» опций, таких как «включающий файл», значения объединяются.

Вот пример сессии:

$ bin/gcc/debug/multiple_sources
Include paths are: /opt
Optimization level is 1
$ bin/gcc/debug/multiple_sources --help
Allows options:
Generic options:
  -v [ --version ]       : print version string
  --help                 : produce help message
Configuration:
  --optimization n       : optimization level
  -I [ --include-path ] path : include path
$ bin/gcc/debug/multiple_sources --optimization=4 -I foo a.cpp b.cpp
Include paths are: foo /opt
Input files are: a.cpp b.cpp
Optimization level is 4

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


PrevUpHomeNext

Статья Tutorial раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 27. Boost.Program_options может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Chapter 27. Boost.Program_options ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:47:41/0.0084571838378906/0