Хотите, чтобы опции были указаны несколько раз при использовании опций программы повышения. Прямо сейчас я получаю несколько случаев

Я использую boost program_options 1.50.0

Я хочу разрешить следующее для моей программы foobar
foobar --debug 2 --debug 3

Из кода boost program_options приведен пример regex.cpp, который показывает создание нового типа и создание валидатора для этого типа.
Я попробовал это, и это работает, но теперь я не могу использовать некоторые другие опции add_options () typed_value, такие как default_value, composing и т. Д.

Вот что я попробовал до сих пор:

    #include <boost/program_options.hpp>

using namespace boost;

using namespace boost::program_options;

#include <iostream>
using namespace std;
struct lastmultioccurrenceint {
public:
lastmultioccurrenceint(int n) : n(n) {}
int n;
};

void validate(boost::any& v,
const std::vector< std::string >& xs,
//const std::vector< std::basic_string<charT> >& xs,
lastmultioccurrenceint* , int)
{
using namespace boost::program_options;

cerr << "IN VALIDATE" << endl;
//validators::check_first_occurrence(v);
string s = validators::get_single_string(xs);
if (!v.empty()) {
cerr << "\tPRINTTING MULTIOCCURENCE WARNING, allowing v to be overwritten" << endl;
cerr << "\tEarlier value was: " <<  boost::any_cast<int>(v) << endl;
cerr << "\tNew value is: " << s << endl;
}
try {
//v = any(lastmultioccurrenceint(lexical_cast<int>(sx)));
//v = any(lexical_cast<int>(sx)); // works
v = any(lexical_cast<int>(s));
//v = any(lexical_cast<lastmultioccurrenceint>(s));
//v = any(4);
//}
/*catch(const bad_lexical_cast&) {
boost::throw_exception(validation_error::invalid_option_value(s));
} */
}
catch(const bad_lexical_cast&) {
throw validation_error(validation_error::invalid_option_value);
}
cerr << "made it through" << endl;

int main (int argc, char **argv) {

variables_map m_varMap;
// define style
//  unix_style =  (allow_short | short_allow_adjacent | short_allow_next
//            | allow_long | long_allow_adjacent | long_allow_next
//            | allow_sticky | allow_guessing
//            | allow_dash_for_short),
// ... allows typical unix-style options
// allow_long_disguise = can use "-" instead of "--"// Reference: http://www.boost.org/doc/libs/1_42_0/doc/html/boost/program_options/command_line_style/style_t.html
//
try {

ProgOpts::command_line_style::style_t style = ProgOpts::command_line_style::style_t(
ProgOpts::command_line_style::unix_style |
//ProgOpts::command_line_style::case_insensitive |
ProgOpts::command_line_style::allow_long_disguise );

options_description options("YDD");

//lastmultioccurrenceint debugOpt;

options.add_options()
("debug", value<lastmultioccurrenceint>(), "debug value (0-4), default is 0 (performance mode)")
//("debug", value<lastmultioccurrenceint>(&debugOpt)->default_value(0)->composing(), "debug value (0-4), default is 0 (performance mode)")
;

//ProgOpts::parsed_options firstPreParsed = ProgOpts::command_line_parser(argc,argv).options(options).style(style).allow_unregistered().run();
ProgOpts::parsed_options firstPreParsed = ProgOpts::command_line_parser(argc,argv).options(options).allow_unregistered().run();
ProgOpts::store(firstPreParsed, m_varMap);

ProgOpts::notify(m_varMap);
}
/*catch (boost::program_options::multiple_occurrences &e) {
cerr << "GOT MULTIPLES" << endl;
cerr << "Option Name: " << e.get_option_name() << endl;
cerr << e.what() << endl;
}
catch(boost::bad_any_cast& e) {
cerr << "WRONG TYPE" << endl;
cerr << e.what() << endl;
} */
catch(std::exception& e) {
cerr << "SOMETHING ELSE" << endl;
cerr << e.what() << endl;
}
catch(...) {
cerr << "UNKNOWN ERROR" << endl;
}

cerr << "DEBUG OPT IS: " << m_varMap["debug"].as<int>() << endl;
}

Так что если я сделаю:
foobar —debug 2 —debug 3

Если я закомментирую текущий вариант отладки ….

("debug", value<lastmultioccurrenceint>(), "debug value (0-4), default is 0 (performance mode)")

… и раскомментируйте следующие две строки:

lastmultioccurrenceint debugOpt;
("debug", value<lastmultioccurrenceint>(&debugOpt)->default_value(0)->composing(), "debug value (0-4), default is 0 (performance mode)")

… тогда это даже не компилируется.

Вы знаете, как это сделать, чтобы он позволял мне использовать default_value и сочинять?
Возможно, он наследуется от typed_value, но я пока не нашел хорошего способа сделать это.

8

Решение

Я не думаю, что вам нужно определять пользовательский тип с помощью валидатора, чтобы достичь желаемого результата. Это можно сделать с помощью существующей семантической информационной поддержки библиотеки. Рассмотрим этот пример

#include <boost/assign/list_of.hpp>
#include <boost/program_options.hpp>
#include <boost/version.hpp>

#include <iostream>

int
main( int argc, char** argv )
{
namespace po = boost::program_options;

po::options_description desc("Options");

typedef std::vector<unsigned> DebugValues;
DebugValues debug;
desc.add_options()
("help,h", "produce help message")
("debug", po::value<DebugValues>(&debug)->default_value(boost::assign::list_of(0), "0")->composing(), "set debug level")

;

po::variables_map vm;
try {
const po::positional_options_description p; // note empty positional options
po::store(
po::command_line_parser( argc, argv).
options( desc ).
positional( p ).
run(),
vm
);
po::notify( vm );

if ( vm.count("help") ) {
std::cout << desc << "\n";
std::cout << "boost version: " << BOOST_LIB_VERSION << std::endl;
return 0;
}
} catch ( const boost::program_options::error& e ) {
std::cerr << e.what() << std::endl;
}

std::cout << "got " << debug.size() << " debug values" << std::endl;
if ( !debug.empty() ) {
DebugValues::const_iterator value( debug.end() );
std::advance( value, -1 );
std::cout << "using last value of " << *value << std::endl;
}
}

и образец использования:

samm$ ./a.out -h
Options:
-h [ --help ]         produce help message
--debug arg (=0)      set debug level

boost version: 1_46_1
samm$ ./a.out --debug 1 --debug 2
got 2 debug values
using last value of 2
samm$ ./a.out --debug 4 --debug 1
got 2 debug values
using last value of 1
samm$ ./a.out --debug 4 --debug 1 --debug 9
got 3 debug values
using last value of 9
samm$
6

Другие решения

Других решений пока нет …