command_line: allow args to depend on more than one args
This commit is contained in:
parent
55f8d917fd
commit
cc9a0bee04
|
@ -33,6 +33,7 @@
|
|||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
|
@ -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<typename T, bool required = false, bool dependent = false>
|
||||
template<typename T, bool required = false, bool dependent = false, int NUM_DEPS = 1>
|
||||
struct arg_descriptor;
|
||||
|
||||
template<typename T>
|
||||
|
@ -98,6 +99,22 @@ namespace command_line
|
|||
bool not_use_default;
|
||||
};
|
||||
|
||||
template<typename T, int NUM_DEPS>
|
||||
struct arg_descriptor<T, false, true, NUM_DEPS>
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
const char* name;
|
||||
const char* description;
|
||||
|
||||
T default_value;
|
||||
|
||||
std::array<const arg_descriptor<bool, false> *, NUM_DEPS> ref;
|
||||
std::function<T(std::array<bool, NUM_DEPS>, bool, T)> depf;
|
||||
|
||||
bool not_use_default;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, true>& /*arg*/)
|
||||
{
|
||||
|
@ -127,6 +144,28 @@ namespace command_line
|
|||
return semantic;
|
||||
}
|
||||
|
||||
template<typename T, int NUM_DEPS>
|
||||
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false, true, NUM_DEPS>& arg)
|
||||
{
|
||||
auto semantic = boost::program_options::value<T>();
|
||||
if (!arg.not_use_default) {
|
||||
std::array<bool, NUM_DEPS> 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<typename T>
|
||||
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false>& arg, const T& def)
|
||||
{
|
||||
|
@ -144,8 +183,8 @@ namespace command_line
|
|||
return semantic;
|
||||
}
|
||||
|
||||
template<typename T, bool required, bool dependent>
|
||||
void add_arg(boost::program_options::options_description& description, const arg_descriptor<T, required, dependent>& arg, bool unique = true)
|
||||
template<typename T, bool required, bool dependent, int NUM_DEPS>
|
||||
void add_arg(boost::program_options::options_description& description, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg, bool unique = true)
|
||||
{
|
||||
if (0 != description.find_nothrow(arg.name, false))
|
||||
{
|
||||
|
@ -214,15 +253,15 @@ namespace command_line
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T, bool required, bool dependent>
|
||||
typename std::enable_if<!std::is_same<T, bool>::value, bool>::type has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent>& arg)
|
||||
template<typename T, bool required, bool dependent, int NUM_DEPS>
|
||||
typename std::enable_if<!std::is_same<T, bool>::value, bool>::type has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg)
|
||||
{
|
||||
auto value = vm[arg.name];
|
||||
return !value.empty();
|
||||
}
|
||||
|
||||
template<typename T, bool required, bool dependent>
|
||||
bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent>& arg)
|
||||
template<typename T, bool required, bool dependent, int NUM_DEPS>
|
||||
bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent, NUM_DEPS>& 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<T>());
|
||||
}
|
||||
|
||||
template<typename T, int NUM_DEPS>
|
||||
T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, false, true, NUM_DEPS>& arg)
|
||||
{
|
||||
std::array<bool, NUM_DEPS> 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<T>());
|
||||
}
|
||||
|
||||
template<typename T, bool required>
|
||||
T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg)
|
||||
{
|
||||
return vm[arg.name].template as<T>();
|
||||
}
|
||||
|
||||
template<bool dependent>
|
||||
inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<bool, false, dependent>& arg)
|
||||
template<bool dependent, int NUM_DEPS>
|
||||
inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<bool, false, dependent, NUM_DEPS>& arg)
|
||||
{
|
||||
return get_arg(vm, arg);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue