2009-11-14 16 views
9

Wenn ich wieGrenze der Präzision auf std :: cout der Standardwerte in boost :: options_description

options.add_options() 
    ("double_val", value(&config.my_double)->default_value(0.2), "it's a double"); 

eine boost :: options_description Instanz konstruieren und später die automatisierte Ausgabe der Optionen haben will, die verfügbar sind für mein Programm, und

std::cout << options << std::endl; 

der Standardwert 0,2 wird gezeigt, mit viel zu hohen Präzision, die effektiv clutters meine Ausgabe, wenn ich lange Variablennamen setzen:

--double_val (=0.20000000000000001) it's a double 

leider an einem Aufruf std :: cout.precision hilft nicht:

cout.precision(5); 
std::cout << options << std::endl; 

führt dies immer noch auf den gleichen Ausgang:/

Haben Sie Ideen, wie das zu begrenzen, Anzeige des Defaultwertes auf weniger Positionen?

Mit freundlichen Grüßen, Christian

Antwort

10

Von boost/program_options/value_semantic.hpp: (! Nie eine sichere Sache mit Boost-)

/** Specifies default value, which will be used 
     if none is explicitly specified. The type 'T' should 
     provide operator<< for ostream. 
    */ 
    typed_value* default_value(const T& v) 
    { 
     m_default_value = boost::any(v); 
     m_default_value_as_text = boost::lexical_cast<std::string>(v); 
     return this; 
    } 

    /** Specifies default value, which will be used 
     if none is explicitly specified. Unlike the above overload, 
     the type 'T' need not provide operator<< for ostream, 
     but textual representation of default value must be provided 
     by the user. 
    */ 
    typed_value* default_value(const T& v, const std::string& textual) 
    { 
     m_default_value = boost::any(v); 
     m_default_value_as_text = textual; 
     return this; 
    } 

So ist die Implementierung ist einfach tot. Der Versuch, den Ostream neu zu konfigurieren, damit die Formatierung wie gewünscht ausgeführt wird, funktioniert nicht, da der Standardwert nur in einer eigenständigen Zeichenfolge ostringstream (innerhalb lexical_cast) in eine Zeichenfolge konvertiert wird.

So eine einfache Problemumgehung ist, die gewünschte Zeichenfolgendarstellung als zweites Argument zu default_value hinzuzufügen. Dann können Sie es drucken, wie Sie wollen (auch nicht, wenn Sie eine leere Zeichenfolge übergeben). Wie so:

value(&config.my_double)->default_value(0.2, "0.2") 

Je mehr „enterprisey“ Weg, um das Gleiche zu erreichen wäre, um Ihre eigene Art umzusetzen, die double wickeln würden, für config.my_double verwendet werden und bieten Bau von und Zwang zu double und Ihrem sehr eigene ostream& operator<< mit genau der Formatierung, die Sie wünschen. Ich schlage diesen Ansatz jedoch nicht vor, es sei denn, Sie schreiben eine Bibliothek, die allgemeingültig ist.

Aus den Boost-lexikalische Gussnoten:

Die vorherige Version von lexical_cast verwendet, um den Standardstrom Präzision für Lesen und Schreiben von Gleitkommazahlen Zahlen. Für Zahlen, die eine entsprechende Spezialisierung von Std :: numeric_limits haben, wählt die aktuelle Version jetzt eine Genauigkeit übereinstimmen.

3

Um zu vermeiden, von Hand zu zitieren mit:

#define QUOTE(x) #x 
#define stringize(x) QUOTE(x) 

#define MY_DOUBLE_DEFAULT 0.2 

value(&config.my_double)->default_value(MY_DOUBLE_DEFAULT, stringize(MY_DOUBLE_DEFAULT))