5

ブースト グラフとプログラム オプションを使用してグラフ ジェネレーターを構築しています。たとえば、2 つのタイプのコンポーネント C と W があり、それぞれに 1 つのソース、1 つのシンク、およびその間のトポロジを指定するいくつかの追加パラメーターがあります。コマンドライン引数の順序で提供される順序でそれらをつなぎ合わせることができるようにしたいと思います。

例えば:

./bin/make_graph -c4,5,1 -w3,3 -c3,1,2

次のようなグラフを作成する必要があります。

C -- W -- C

しかし:

./bin/make_graph -c4,5,1 -c3,1,2 -w3,3

次のようなグラフを作成する必要があります。

C -- C -- W

boost::program_options を使用すると、同じ string_key のオプションを value_type == vector< string > (私の場合) のマップに「構成」するため、正確な順序を抽出する方法を特定できませんでした。

マップを反復処理すると、順序が失われます。解析を複製せずに、オプションが解析されるたびに関数 (おそらくコールバック) を呼び出す方法はありますか? この方向のドキュメントは見つかりませんでした。他の提案はありますか?

私がこれをでっち上げているわけではないことを納得させるために、これまでのところ私が持っているものは次のとおりです。

    namespace bpo = boost::program_options;
    std::vector<std::string> args_cat, args_grid, args_web;
    bpo::options_description desc("Program options:");
    desc.add_options()
            .operator ()("help,h","Displays this help message.")
            .operator ()("caterpillar,c",bpo::value< std::vector<std::string> >(&args_cat)->default_value( std::vector<std::string>(1,"4,7,2"), "4,7,2" ),"Caterpillar tree with 3 parameters")
            .operator ()("grid,g",bpo::value< std::vector<std::string> >(&args_grid)->default_value( std::vector<std::string>(1,"3,4"), "3,4" ),"Rectangular grid with 2 parameters")
            .operator ()("web,w",bpo::value< std::vector<std::string> >(&args_web)->default_value( std::vector<std::string>(1,"3,4"), "3,4" ),"Web with 2 parameters")
            ;
    bpo::variables_map ops;
    bpo::store(bpo::parse_command_line(argc,argv,desc),ops);
    bpo::notify(ops);
    if((argc < 2) || (ops.count("help"))) {
        std::cout << desc << std::endl;
        return;
    }
    //TODO: remove the following scope block after testing
    {
        typedef bpo::variables_map::iterator OptionsIterator;
        OptionsIterator it = ops.options.begin(), it_end = ops.options.end();
        while(it != it_end) {
            std::cout << it->first << ": ";
            BOOST_FOREACH(std::string value, it->second) {
                std::cout << value << " ";
            }
            std::cout << std::endl;
            ++it;
        }
        return;
    }

タイプをパラメーターとして含めることもでき、この問題を自明に解決できることを認識しています。

./bin/make_graph --component c,4,5,1 --component w,3,3 --component c,3,1,2

しかし、それはパーサー/バリデーターを自分で書く方向に進んでいます(おそらくブーストプログラムオプションを使用しなくても):

./bin/make_graph --custom c,4,5,1,w,3,3,c,3,1,2
./bin/make_graph c,4,5,1,w,3,3,c,3,1,2

これをエレガントな方法で行うことをどのように勧めますか?

前もって感謝します!

PS: これを投稿する前に SO で "[boost] +sequence program options" と "[boost-program-options] +order" (およびそのバリアント) を検索しました。重複。

4

2 に答える 2

4

質問を投稿してから、掘り下げて、上記の既存の例で機能する「ハック」を作成しました。

bpo::parsed_options p_ops = bpo::parse_command_line(argc,argv,desc);
typedef std::vector< bpo::basic_option<char> >::iterator OptionsIterator;
OptionsIterator it = p_ops.options.begin(), it_end = p_ops.options.end();
while(it != it_end) {
    std::cout << it->string_key << ": ";
    BOOST_FOREACH(std::string value, it->value) {
        std::cout << value << " ";
    }
    std::cout << std::endl;
    ++it;
}

私がこれをハックと呼ぶ理由は、すべての引数に文字列としてアクセスし、.as<T>()メンバー関数で bpo::variables_map が行うのと同じように、そこから型を抽出する必要があるためです。編集: options 構造体のメンバーにも直接アクセスします。

于 2012-08-02T17:16:58.640 に答える
2

これはどう:

./bin/make_graph c,4,5,1 c,3,1,2 w,3,3

ここ"c,4,5,1"で、"c,3,1,2""w,3,3"は(このチュートリアルのように) に (順番に) 格納される位置引数です。次に、Boost.Tokenizerまたはを使用して、各引数文字列からサブトークンを抽出します。std::vector<std::string>--input-fileboost::algorithm::split

グラフが複雑になる可能性がある場合は、ユーザーがグラフ パラメータを含む入力ファイルを指定できるようにすることを検討する必要があります。Boost.Program_Options は、コマンド ライン オプションと同じ構文を使用するユーザー構成ファイルを解析できます。

于 2012-08-02T03:27:03.167 に答える