2009-11-14 5 views
9

Quand je construis un coup de pouce :: instance options_description commelimite la précision sur std :: Cout des valeurs par défaut dans boost :: options_description

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

et que vous voulez plus tard que la sortie automatique des options disponibles pour mon programme, et de mettre

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

la valeur par défaut 0,2 est montré avec précision manière trop élevée, ce qui effectivement encombre ma sortie quand j'ai longues noms de variables:

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

malheureusement, un appel avant std :: cout.precision n'a pas aidé:

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

cela conduit toujours à la même sortie:/

Avez-vous des idées sur la façon de limiter la affichage de la valeur par défaut à moins de positions?

Meilleures salutations, Christian

Répondre

10

De boost/program_options/value_semantic.hpp: (Ne jamais une chose sûre 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; 
    } 

Ainsi, la mise en œuvre est simple comme. Essayer de reconfigurer votre ostream pour que le formatage sorte comme vous voulez ne fonctionnera pas, car la valeur par défaut est juste convertie en une chaîne dans un ostringstream autonome (à l'intérieur de lexical_cast).

Une solution de contournement simple consiste donc à ajouter la représentation de chaîne souhaitée en tant que second argument à default_value. Ensuite, vous pouvez le faire imprimer comme vous voulez (y compris pas du tout, si vous passez une chaîne vide). Comme si:

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

Plus façon d'accomplir la même chose « enterprisey » serait de mettre en œuvre votre propre type qui envelopperait double, être utilisé pour config.my_double et fournir la construction de et la contrainte à double, et votre très posséder ostream& operator<< avec exactement le formatage que vous désirez. Cependant, je ne suggère pas cette approche, sauf si vous écrivez une bibliothèque qui exige la généralité.

Des notes Boost lexicales Cast:

La version précédente de lexical_cast utilisé la précision de flux par défaut pour lecture et d'écriture à virgule flottante numéros. Pour les nombres qui ont une spécialisation correspondante de std :: numeric_limits, la version actuelle choisit maintenant une précision à .

3

Pour éviter d'avoir à citer à la main:

#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)) 
Questions connexes