2016-04-22 9 views
4

Angenommen, ich habe ein Programm mit boost :: program_options Befehlszeilenargumente zu analysieren, und man hat einen unsigned Wert:Verbieten negatives Argument für unsigned Wert mit boost :: program_options

#include <boost/program_options.hpp> 
#include <iostream> 

namespace po = boost::program_options; 

int main(int argc, char* argv[]) { 
    unsigned num; 
    po::options_description desc; 
    desc.add_options() 
     ("num,n", po::value<unsigned>(&num), "Non-negative number"); 
    po::variables_map vm; 
    po::store(po::parse_command_line(argc, argv, desc), vm); 
    po::notify(vm); 
    std::cout << "Number: " << num << '\n'; 
    return 0; 
} 

Dann, wenn ich eine negative passieren Wert auf der Kommandozeile, akzeptiert sie es und wickelt sie um:

$ ./bponeg -n -1 
Number: 4294967295

ich würde eher, dass negative Zahlen einen Fehler lösen das gleiche (dh invalid_option_value werfen), wie es wäre, wenn ich ./bponeg -n abc schreibe. Von meinem eigenen Code nach dem Parsing scheint es unmöglich zu unterscheiden zwischen dem Fall, in dem der Benutzer schrieb -1 oder wenn sie 4294967295 schrieb.

Kann ich den Parser programm_options anweisen, negative Eingaben für unsigned Werte abzulehnen?

+4

Lesen Sie einfach einen vorzeichenbehafteten Wert und prüfen Sie, ob es negativ ist. Ich bin kein Freund davon, unsignierte Typen für irgendetwas anderes zu benutzen, als nur irgendwie zu fummeln. (Ib4 der übliche Hass: Einige Mitglieder des Normenausschusses stimmen mir zu, siehe zB [dieses Panel] (https://channel9.msdn.com/Events/GoingNative/2013/Interactive-Panel-Ask-Us-Anything) 9 : 50, 42:40, 1:02:50) –

+3

@BaummitAugen Was ist mit Situation, in der unsigned value migh außerhalb der Reichweite von signed liegt? –

+2

@Revolver_Ocelot Wenn Sie das zusätzliche Bit benötigen und die nächst größere Ganzzahl mit Vorzeichen keine Option ist, müssen Sie tun, was Sie tun müssen. So weit ist es mir noch nie passiert. vOv –

Antwort

7

Sie könnte schreiben eine custom validator, die so etwas wie sein würde:

struct nonnegative { 
    unsigned value; 
}; 

void validate(boost::any& v, const std::vector<std::string>& values, nonnegative*, int) 
{ 
    using namespace boost::program_options; 
    validators::check_first_occurrence(v); 

    std::string const& s = validators::get_single_string(values); 
    if (s[0] == '-') { 
     throw validation_error(validation_error::invalid_option_value); 
    } 

    v = lexical_cast<unsigned>(s); 
} 

Und dann benutzen Sie einfach eine nonnegative anstelle eines unsigned.

Aber ich denke, es wäre einfacher, nur eine int64_t zu verwenden und einen Fehler zu werfen, wenn es negativ ist. Auch weniger Code.