From cc9a0bee04658de1a085bc9c038c4e7e4468ac7c Mon Sep 17 00:00:00 2001 From: stoffu Date: Sun, 4 Mar 2018 17:08:42 +0900 Subject: [PATCH] command_line: allow args to depend on more than one args --- src/common/command_line.h | 66 +++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/src/common/command_line.h b/src/common/command_line.h index 2f64f5448..3a869bb26 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,7 @@ namespace command_line //! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`. bool is_no(const std::string& str); - template + template struct arg_descriptor; template @@ -98,6 +99,22 @@ namespace command_line bool not_use_default; }; + template + struct arg_descriptor + { + typedef T value_type; + + const char* name; + const char* description; + + T default_value; + + std::array *, NUM_DEPS> ref; + std::function, bool, T)> depf; + + bool not_use_default; + }; + template boost::program_options::typed_value* make_semantic(const arg_descriptor& /*arg*/) { @@ -127,6 +144,28 @@ namespace command_line return semantic; } + template + boost::program_options::typed_value* make_semantic(const arg_descriptor& arg) + { + auto semantic = boost::program_options::value(); + if (!arg.not_use_default) { + std::array depval; + depval.fill(false); + std::ostringstream format; + format << arg.depf(depval, true, arg.default_value); + for (size_t i = 0; i < depval.size(); ++i) + { + depval.fill(false); + depval[i] = true; + format << ", " << arg.depf(depval, true, arg.default_value) << " if '" << arg.ref[i]->name << "'"; + } + for (size_t i = 0; i < depval.size(); ++i) + depval[i] = arg.ref[i]->default_value; + semantic->default_value(arg.depf(depval, true, arg.default_value), format.str()); + } + return semantic; + } + template boost::program_options::typed_value* make_semantic(const arg_descriptor& arg, const T& def) { @@ -144,8 +183,8 @@ namespace command_line return semantic; } - template - void add_arg(boost::program_options::options_description& description, const arg_descriptor& arg, bool unique = true) + template + void add_arg(boost::program_options::options_description& description, const arg_descriptor& arg, bool unique = true) { if (0 != description.find_nothrow(arg.name, false)) { @@ -214,15 +253,15 @@ namespace command_line } } - template - typename std::enable_if::value, bool>::type has_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) + template + typename std::enable_if::value, bool>::type has_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) { auto value = vm[arg.name]; return !value.empty(); } - template - bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor& arg) + template + bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor& arg) { return vm[arg.name].defaulted(); } @@ -233,14 +272,23 @@ namespace command_line return arg.depf(get_arg(vm, arg.ref), is_arg_defaulted(vm, arg), vm[arg.name].template as()); } + template + T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) + { + std::array depval; + for (size_t i = 0; i < depval.size(); ++i) + depval[i] = get_arg(vm, *arg.ref[i]); + return arg.depf(depval, is_arg_defaulted(vm, arg), vm[arg.name].template as()); + } + template T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) { return vm[arg.name].template as(); } - template - inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) + template + inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) { return get_arg(vm, arg); }