17
//Using boost program options to read command line and config file data
    #include <boost/program_options.hpp>
    using namespace std;
    using namespace boost;
    namespace po = boost::program_options;

int main (int argc, char *argv[])
{
    po::options_description config("Configuration");
    config.add_options()
                ("IPAddress,i","IP Address")
                ("Port,p","Port")
                 ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, config),vm);
    po::notify(vm);

    cout << "Values\n";

    string address = (vm["IPAddress"].as<std::string >()).c_str();
    string port = (vm["Port"].as<std::string>()).c_str();

    cout << (vm["IPAddress"].as< string >()).c_str();
    cout << " " << (vm["Port"].as<string>()).c_str();

    return 0;

}

入力された値は何らかの形で印刷できませんか?

これがgdbの出力です。キャストの問題のようです:

「boost::exception_detail::clone_impl」のインスタンスをスローした後に呼び出される終了

' what(): boost::bad_any_cast: boost::any_cast を使用した変換に失敗しました

        Program received signal SIGABRT, Aborted.
        0x0000003afd835935 in raise () from /lib64/libc.so.6
string address = (vm["IPAddress"].as<std::string >()).c_str();

エラーが発生した場所です。std::string と string を試しましたが、同じ結果が得られました。

testboostpo -i 192.168.1.10 -p 5000

コマンドラインです。

次のように、型を宣言してみました。

config.add_options()
        ("IPAddress,i", po::value<std::string>(), "IP Address")
            ("Port,p", po::value<std::string>(), "Port");

それでもエラーが発生しました。

これは本物のバグでしょうか?

4

5 に答える 5

17

の 2 つの引数のオーバーロードが型を指定していないため、boost::bad_any_castからスローされた例外が表示されます。そのため、 への変換は機能しません。値を に変換する必要があり、アプリケーションで必要な場合は、値セマンティックを使用します。po::variables_mapconst char*po::options_description_easy_init::operator()po::value_semanticstd::stringstd::stringrequired()

#include <boost/program_options.hpp>
namespace po = boost::program_options;

int main (int argc, char *argv[])
{
    po::options_description config("Configuration");
    config.add_options()
                ("IPAddress,i", po::value<std::string>()->required(), "IP Address")
                ("Port,p", po::value<std::string>()->required(), "Port")
                ;

    try {
        po::variables_map vm;
        po::store(po::parse_command_line(argc, argv, config),vm);
        po::notify(vm);
        std::cout << "Values" << std::endl;

        const std::string address = vm["IPAddress"].as<std::string>();
        const std::string port = vm["Port"].as<std::string>();

        std::cout << "address: " << address << std::endl;
        std::cout << "port: " << port << std::endl;
    } catch ( const std::exception& e ) {
        std::cerr << e.what() << std::endl;
        return 1;
    }

    return 0;
}

追加された catch ブロックに注意してください。これは、解析によって例外がスローされる可能性がある (そして、お気付きのようにスローされる) ためです。サンプル セッションは次のとおりです。

samm$ ./a.out
the option '--IPAddress' is required but missing
samm$ ./a.out --IPAddress 127.0.0.1
the option '--Port' is required but missing
samm$ ./a.out --IPAddress 127.0.0.1 --Port 5000
Values
address: 127.0.0.1
port: 5000
samm$ 

これは、COMpile LINK RUn (coliru) の厚意による、同じ動作を示すオンライン デモです。

于 2013-03-20T21:59:28.993 に答える
4

オプションを追加するときは、ip-address と port を文字列として宣言する必要があります。

config.add_options()
    ("IPAddress,i", po::value<std::string>(), "IP Address")
    ("Port,p", po::value<std::string>(), "Port")
    ;
于 2013-03-20T21:48:54.537 に答える
2

この同じメッセージは、オプションの引数を正しく処理していない場合にも発生する可能性があります。

サムのソリューションは必須の引数を釘付けにし、OPのコードは必須を示唆しています-それらを必須としてマークするだけです。オプションの入力については、Boost PO チュートリアルで、変換前にオプションが存在するかどうかを確認するためのテンプレートが提供されます。

if(vm.count("address")) 
{
    const std::string address = vm["IPAddress"].as<std::string>();
    std::cout << "address: " << address << std::endl;
}
if(vm.count("port")) 
    const std::string port = vm["Port"].as<std::string>();
    std::cout << "port: " << port << std::endl;
}

私の問題-コピー/貼り付けして、ifテストを使用法に合わせるのを忘れていました!

于 2016-04-11T00:27:46.397 に答える
1

同様のエラー メッセージが表示されましたが、省略形の を使用していたためiですIPAddress

// this throws the cast exception
const std::string address = vm["i"].as<std::string>();
// this does not
const std::string address = vm["IPAddress"].as<std::string>();

ブーストは最初に宣言されたものを取ります。したがって、オプションが を使用する必要があると宣言されIPAddress,iている場合vm["IPAddres"]、を使用i,IPAddressする必要がありますvm["i"]

于 2021-01-21T22:39:00.403 に答える
0

この男が抱えていたのと必ずしも同じ問題ではありませんが、ここに私を捕まえたものがあります:

型を匿名名前空間に配置すると、名前が同じでインスタンスが異なる 2 つのクラスが存在し、キャストは失敗します。例えば:

a.hpp:

namespace {
class MyClass {...};
}

b.cpp:

#include "a.hpp"
cli_options.add_options()("test", po::value<MyClass>(), "test desc");

c.cpp:

#include "a.hpp" // THIS WILL MAKE A DIFFERENT "MyClass"
vm["test"].as<MyClass>();  // Fails at runtime.

MyClassinb.cppと inc.cppが同じクラスではないため、失敗します。匿名の名前空間のため。

匿名の名前空間を削除すると、問題が解決します。

于 2018-03-11T15:15:26.193 に答える