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 <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <array>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include <boost/program_options/parsers.hpp>
|
#include <boost/program_options/parsers.hpp>
|
||||||
|
@ -48,7 +49,7 @@ namespace command_line
|
||||||
//! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`.
|
//! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`.
|
||||||
bool is_no(const std::string& str);
|
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;
|
struct arg_descriptor;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -98,6 +99,22 @@ namespace command_line
|
||||||
bool not_use_default;
|
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>
|
template<typename T>
|
||||||
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, true>& /*arg*/)
|
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, true>& /*arg*/)
|
||||||
{
|
{
|
||||||
|
@ -127,6 +144,28 @@ namespace command_line
|
||||||
return semantic;
|
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>
|
template<typename T>
|
||||||
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false>& arg, const T& def)
|
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;
|
return semantic;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, bool required, bool dependent>
|
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>& arg, bool unique = true)
|
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))
|
if (0 != description.find_nothrow(arg.name, false))
|
||||||
{
|
{
|
||||||
|
@ -214,15 +253,15 @@ namespace command_line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, bool required, bool dependent>
|
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>& arg)
|
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];
|
auto value = vm[arg.name];
|
||||||
return !value.empty();
|
return !value.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, bool required, bool dependent>
|
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>& arg)
|
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();
|
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>());
|
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>
|
template<typename T, bool required>
|
||||||
T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg)
|
T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg)
|
||||||
{
|
{
|
||||||
return vm[arg.name].template as<T>();
|
return vm[arg.name].template as<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool dependent>
|
template<bool dependent, int NUM_DEPS>
|
||||||
inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<bool, false, dependent>& arg)
|
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);
|
return get_arg(vm, arg);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue