yhtの日記: boost.program_option~2
前のboost::program_option~1ではコマンドライン・オプションを読み込む簡単な例を見たが, オプションにデフォルト値を与えたり、色々な型のオプションを使えたりすると便利なので、 ちょっとした応用編。
例によって、boost.orgのドキュメントを参照の事。この例の全ソースはlibs/program_options/example/options_description.cpp
以下は、直訳・意訳・妄想・実験結果等。
前回と同様、
#include <boost/program_options.hpp>
using namespace boost;
namespace po = boost::program_options;
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
とお約束から始まる。
次に、前回と同様にpo::options_descriptionクラスの変数を用意してサポートするオプションを登録してゆくのだが、今回は少し変えてある。
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」オプションは、前回の「compression」と次の2点で異なる。
1. 変数のアドレス(&opt)を指定している。この変数の中にオプションの値が入っていく。
2. ユーザーが指定しなかった場合のオプションのデフォルト値10を指定している。
「include-path」オプションはinclude pathをコマンドラインから読み込み(複数可)、 std::vector<std::string>に入れる。別名として、短縮形「-I」でも受け付ける。 また、options_descriptionクラスのインターフェースが一つのソース(コマンドライン)だけ から読み込む唯一の例になっている。
「input-file」オプションは、処理すべきファイルのリストで、
compiler --input-file=a.cpp
というように使うことになり、
compiler a.cpp
という標準的な使い方と比べると少し変だが、初めてだからよいだろう。
上の例のように、オプションの名前の無いコマンドライン・トークンを、 このライブラリでは``positional options''と呼び、この種類のものも 読み込む事が出来る。ユーザーの若干の骨折りで、``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);
の最初の2行。後半4行でコマンドラインからvmへオプションを読み込んでいる。 前回はpo::parse_command_line()函数で読み込んだ(簡素な読み込みルールの場合は こちらが便利)が、より詳しい情報をやり取りする必要があり、po::command_line_parser クラスを利用する。
これでオプションの読み込みが済んだので、コンパイラの実装は省略し、オプションの 表示のみをする。
if (vm.count("help")) {
cout << "Usage: options_description [options]\n";
cout << desc;
return 0;
}
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";
必要なコードは実装したので、コンパイルと実行。
%g++ -o odesc -O2 options_description.cpp -lboost_program_options-mt
%
でコンパイル。-lboost_program_optionsでもよい。
%./odesc --help
Usage: options_description [options]
Allowed options:
--help produce help message
--optimization arg (=10) optimization level
-I [ --include-path ] arg include path
--input-file arg input file
%./odesc -I /usr/local/include a.cpp
Include paths are: /usr/local/include
Input files are: a.cpp
Optimization level is 10
%./odesc -I /usr/local/include a.cpp --optimization 15
Include paths are: /usr/local/include
Input files are: a.cpp
Optimization level is 15
%
さて、上の例でまだちょっとした問題が残っている。 それは``--input-file''オプションを指定できることと、表示されていること。 オプションを隠すのは次の例まで待ってほしい。