SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

コマンドラインの解析

Boost.program_optionsのご紹介

 次に-O,-Iオプション。これらはそれぞれint,string型のオプション値が後続します。さらに-Oには指定しない場合のデフォルト値がありますし、-Iは複数指定できます。コードはこんなカンジ:

list03
#include <iostream>
#include <vector>
#include <string>
#include <boost/program_options.hpp>

namespace po = boost::program_options;
using namespace std;

int main(int argc, char* argv[]) { 
  try {
    po::options_description desc("オプションの説明");
    desc.add_options()
      ("help,h"      , "ヘルプの出力")
      ("optimize,O"  , po::value<int>()->value_name("<N>")->default_value(0), "最適化レベル")
      ("include,I"   , po::value<vector<string>>()->value_name("<path>"), "インクルード・パス")
     ;

    po::command_line_parser parser(argc,argv);
    parser.options(desc);

    po::variables_map vm;
    po::store(parser.run(), vm);
    po::notify(vm);    

    if ( vm.count("help") ) {
      cout << "mycc [option]... <input_file>...\n"
           << desc << endl;
      return 0;
    }
    cout << "optimize level=" << vm["optimize"].as<int>() << endl;
    if ( vm.count("include") ) {
      vector<string> includes = vm["include"].as<vector<string>>();
      cout << "include = ";
      for ( string path : includes ) cout << path << ' ';
      cout << endl;
    }
    return 0;

  } catch(exception& e) {
    cerr << "error: " << e.what() << "\n";
  } catch(...) {
    cerr << "Exception of unknown type!\n";
  }
  return 1;
}

 options_descriptionのadd_options()に続くオプション設定の第2引数にvalue<型>()を置くことでオプション値が後続することを教えてあげます。--include/-Iに対しては、オプション値の型をvector<string>とすることで複数指定可です。

 オプション値はvariables_map vmに対してvm["オプション名"].as<型>()で取得できます。

 myccがコンパイル対象とするfoo.cのような入力ファイルには-,--で始まるオプションスイッチがありません。Boost.program_optionsでは、オプションスイッチを持たないオプションをpositional optionと称しています。positional optionの解析はこんなカンジ:

list04
...
  po::options_description visible("オプションの説明");
  visible.add_options()
    ("help,h"      , "ヘルプの出力")
    ("compile,c"   , "コンパイルのみ")
    ("optimize,O"  , po::value<int>()->value_name("<N>")->default_value(0), "最適化レベル")
    ("include,I"   , po::value<vector<string>>()->value_name("<path>"), "インクルード・パス")
   ;

  po::options_description hidden("Hidden options");
  hidden.add_options()
    ("input_file", po::value<vector<string>>(), "入力ソースコード")
   ;

  // visible と hidden を足し合わせて desc を作る
  po::options_description desc;
  desc.add(visible).add(hidden);

  // オプションスイッチのないオプション pos
  po::positional_options_description pos;
  pos.add("input_file",-1);

  // desc と pos をパーサーに食わす
  po::command_line_parser parser(argc,argv);
  parser.options(desc).positional(pos);

  po::variables_map vm;
  po::store(parser.run(), vm);
  po::notify(vm);    

  typedef boost::optional<po::variable_value> option_t;
  auto get = [&vm](const string& name) {
    return vm.count(name) ? option_t(vm[name]) : option_t();
  };

  option_t compile_opt  = get("compile");
  option_t optimize_opt = get("optimize");
  option_t include_opt  = get("include");
  option_t input_opt    = get("input_file");

  if ( get("help") ) {
    cout << "mycc [option]... <input_file>...\n"
         << visible << endl;
    return 0;
  }
  if ( compile_opt ) { cout << "compile only" << endl; }
  if ( optimize_opt ) { cout << "optimize = " << optimize_opt->as<int>() << endl; }
  if ( include_opt ) {
    vector<string> includes = include_opt->as<vector<string>>();
	cout << "include = ";
	for ( string path : includes ) cout << path << ' ';
	cout << endl;
  }
  if ( input_opt ) {
    vector<string> inputs = input_opt->as<vector<string>>();
	cout << "input files = ";
	for ( string file : inputs ) cout << file << ' ';
	cout << endl;
  }
...

 options_description visibleとhiddenを足し合わせてdescを作っています。こうすることで--help時にvisibleのみをヘルプ出力の対象にして、ヘルプに現れない隠しオプションが実現できます。

 オプション値の取得は、Boost.optionalと小さなラムダ式で少しばかりコードを涼しくしました。

次のページ
コンソールアプリの実装

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/7243 2013/07/16 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー