2011-11-17 11 views
36

Mam dwie pokrewnych pytania:wektorowe argumenty Google Boost opcji programu

  1. Jaki jest sposób Najprostszym aby umożliwić przekazując szereg wartości, używając motywujące Opcje programu? Moim celem jest uniknięcie prog --opt 1 --opt 2 --opt 3 i zamiast tego mam prog --opt 1 2 3.

  2. Co to jest najprostszy sposób, aby mieć opcję, która przybiera dokładnie dwie liczby, np. prog --opt 137 42?

(nie potrzeba żadnych "wolnych" Parametry programu.)

Odpowiedz

29

Dla pierwszej części, to powinno działać

namespace po = boost::program_options; 
po::option_descriptions desc(""); 

desc.add_options() 
("opt", po::value<std::vector<int> >()->multitoken(), "description"); 

Druga część, wymaga nieco więcej pracy. Funkcja po::value zwraca po::typed_value< T, charT > na której trzeba zastąpić zachowanie kilku funkcji, jak następuje

template< typename T, typename charT = char > 
class fixed_tokens_typed_value : public po::typed_value< T, charT > { 
    unsigned _min, _max; 

    typedef po::typed_value< T, charT > base; 

public: 

    fixed_tokens_typed_value(T * t, unsigned min, unsigned max) 
    : _min(min), _max(max), base(t) { 
     base::multitoken(); 
    } 

    virtual multi_typed_value* min_tokens(unsigned min) { 
     _min = min; 
     return *this; 
    } 
    unsigned min_tokens() const {return _min;} 

    virtual multi_typed_value* max_tokens(unsigned max) { 
     _max = max; 
     return *this; 
    } 
    unsigned max_tokens() const {return _max;} 

    base* zero_tokens() { 
     _min = _max = 0; 
     base::zero_tokens(); 
     return *this; 
    } 
} 

który musi towarzyszyć

template< typename T > 
fixed_tokens_typed_value<T> 
fixed_tokens_value(unsigned min, unsigned max) { 
    return fixed_tokens_typed_value<T>(0, min, max); } 

template< typename T > 
fixed_tokens_typed_value<T> 
fixed_tokens_value(T * t, unsigned min, unsigned max) { 
    fixed_tokens_typed_value<T>* r = new 
        fixed_tokens_typed_value<T>(t, min, max); 
    return r; } 

Następnie

desc.add_options() 
("opt", po::fixed_tokens_value<std::vector<int> >(2,2), "description"); 

powinno działać. Nie miałem jeszcze okazji go przetestować, więc prawdopodobnie zawiera kilka błędów. Ale przynajmniej powinno dać ci wyobrażenie o tym, czego potrzebujesz.

+0

@Szabolcs, ciekawym punkcie z tego kod jest taki, że domyślnie wymaga to użycia wektorów. W przeciwnym razie, w jaki sposób zamierzasz przechowywać wartości? Myślę więc, że 'po :: typedvalue < T, charT >' powinno zostać zmienione na 'po :: typedvalue , charT>'. – rcollyer

+0

Czy to również działa dla 'std :: array's lub' std :: lists's zamiast wektorów? – einpoklum

+0

@einpoklum Nie rozumiem, dlaczego nie. Ale myślę, że 'std :: array' będzie trochę skomplikowany, ponieważ nie wiem, co jest używane do wstawienia do kontenera, chociaż jest to prawdopodobnie konfigurowalne, a jego stały rozmiar wymagałby jakiejś adaptacji. Natomiast "std :: list" nie ma tych ograniczeń, więc podejrzewam, że można go użyć jako kropli zastępczej. – rcollyer

37

To jest późna odpowiedź, ale mam nadzieję, że komuś pomaga. Można łatwo wykorzystać tę samą technikę w punkcie 1, z wyjątkiem trzeba dodać kolejną walidacji od liczby elementów w wektorze:

z przykładu rcollyer za:

namespace po = boost::program_options; 
po::option_descriptions desc(""); 

desc.add_options() 
("opt", po::value<std::vector<int> >()->multitoken(), "description"); 

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

vector<int> opts; 
if (!vm["opt"].empty() && (opts = vm["opt"].as<vector<int> >()).size() == 2) { 
    // good to go 
} 
+0

+1 - Szybkie FYI brakuje argumentu z szablonu 3 linii od dołu. – Hazok

+0

Naprawiłem to dzięki. Wygląda na to, że kompilator VC 10 nie jest wrażliwy na ten problem, ponieważ nie dostałem błędu podczas testowania go w oryginalnej formie. – Bee

+0

Powinienem był o tym pomyśleć. +1 – rcollyer

Powiązane problemy