2017-04-23 15 views
0

私はprogram_optionsカスタム検証を理解しようとしています。これは、PythonコードをC++に変換するためです。私は検証機能にブーストprogram_optionsファイルで元の関数を見つけようと
イムをオーバーロードしていることを例に読むが、私の元検証機能がどこにある無駄
にすべてのボディは、ちょうど私に言うことができる
任意の方法
過負荷LLそれ
それは愚かな質問ですが、私はそれが検証の概念とどのようにそれは私の1行コメントを拡張し、事前boost program_optionsカスタム検証

+0

私はこれをしなかった方法は、各オプションの新しいタイプを作成することによってでした。その後、 'operator <<' and '>>'をオーバーロードします。私は 'operator <<'でバリデーションを行います。 –

答えて

0


おかげで行われている程度のアイデアを得るために、デフォルトでの検証方法を知りたい、I boost :: program_optionsが引数validaに少し不足していることが常に判明しています。

この結果、オプションの種類ごとにカスタムクラスを作成する方が簡単なことがわかりました。通常、program_optionsはoperator>>を使用してオプション値をデコードします。したがって、これをオーバーライドすると、program_optionsが認識する例外がスローされます。ネストされた例外を使用すると、非常に詳細なエラー診断を出力できます。

例:

#include <boost/program_options.hpp> 
#include <iostream> 
#include <iomanip> 
#include <sstream> 

namespace po = boost::program_options; 

// a custom option type 
struct foo_or_bar { 
    std::string value; 

    // self-describing 
    static constexpr const char *option_name() { return "foo"; } 

    static constexpr const char *description() { return "single option only. value must be either foo or bar"; } 

    // check the value and throw a nested exception chain if it's wrong  
    void check_value() const 
    try { 
     if (value != "foo" and value != "bar") { 
      std::ostringstream ss; 
      ss << "value must be foo or bar, you supplied " << std::quoted(value); 
      throw std::invalid_argument(ss.str()); 
     } 
    } 
    catch (...) { 
     std::throw_with_nested(po::validation_error(po::validation_error::invalid_option_value, option_name())); 

    } 

    // overload operators 
    friend std::istream &operator>>(std::istream &is, foo_or_bar &arg) { 
     is >> arg.value; 
     arg.check_value(); 
     return is; 
    } 

    friend std::ostream &operator<<(std::ostream &os, foo_or_bar const &arg) { 
     return os << arg.value; 
    } 

}; 

// test 
void test(int argc, const char **argv) { 
    foo_or_bar my_foo; 

    po::options_description desc("test options"); 
    desc.add_options() 
      (foo_or_bar::option_name(), po::value(&my_foo), foo_or_bar::description()); 

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


    std::cout << "foo is " << my_foo << std::endl; 
} 

void print_exception(const std::exception& e, int level = 0) 
{ 
    std::cerr << std::string(level, ' ') << "exception: " << e.what() << '\n'; 
    try { 
     std::rethrow_if_nested(e); 
    } catch(const std::exception& e) { 
     print_exception(e, level+1); 
    } catch(...) {} 
} 

int main() { 
    { 
     std::vector<const char *> test_args = { 
       "executable_name", 
       "--foo=bar" 
     }; 
     test(test_args.size(), test_args.data()); 
    } 

    try { 
     std::vector<const char *> test_args = { 
       "executable_name", 
       "--foo=bob" 
     }; 
     test(test_args.size(), test_args.data()); 
    } 
    catch (std::exception const &e) { 
     print_exception(e); 
    } 
} 

予想される出力:

foo is bar 
exception: the argument for option '--foo' is invalid 
exception: value must be foo or bar, you supplied "bob" 
+0

ur返信ありがとう –

+0

ur返信ありがとうございます..まだ私は式 "静的constexpr const char *" alittle複雑な..を見つけるために私はそれが静的 "constellpr中に生きている" "それは本当にconst charに続いているので、私は理解していない" ....しかし、コンセプトのappraochは素晴らしいです...私は関数の検証の位置を探していたと私はいくつかのフォーラムでは、 ....お返事ありがとうございました –