Ограничьте точность значений std :: cout по умолчанию в boost :: options_description - PullRequest
10 голосов
/ 14 ноября 2009

Когда я создаю экземпляр boost :: options_description, как

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

и позже хотите автоматически выводить параметры, доступные для моей программы, и ставить

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

значение по умолчанию 0.2 показано со слишком высокой точностью, что эффективно загромождает мой вывод, когда у меня длинные имена переменных:

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

к сожалению, предыдущий вызов std :: cout.precision не помог:

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

это приводит к тому же выводу: /

Есть ли у вас идеи, как ограничить отображение значения по умолчанию меньшим количеством позиций?

С наилучшими пожеланиями, Christian

Ответы [ 2 ]

11 голосов
/ 15 ноября 2009

С boost/program_options/value_semantic.hpp:

    /** 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;
    }

Таким образом, реализация очень проста (никогда не бывает уверенным в Boost!). Попытка перенастроить ваш ostream, чтобы форматирование получилось так, как вы хотите, не будет работать, потому что значение по умолчанию просто преобразуется в строку в автономном ostringstream (внутри lexical_cast).

Итак, простой обходной путь - добавить желаемое строковое представление в качестве второго аргумента в default_value. Затем вы можете распечатать его так, как хотите (в том числе и вовсе, если вы пропустите пустую строку). Вот так:

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

Более "предприимчивым" способом для достижения той же цели было бы реализовать свой собственный тип, который бы обернул double, использовался бы для config.my_double, и предоставил бы конструкцию и приведение к double, и ваш собственный ostream& operator<< с точно желаемым форматированием. Однако я не предлагаю такой подход, если только вы не пишете библиотеку, требующую универсальности.

Из Boost Lexical Cast примечания:

Предыдущая версия lexical_cast используется точность потока по умолчанию для чтение и запись с плавающей точкой номера. Для чисел, которые имеют соответствующая специализация std :: numeric_limits, текущий версия теперь выбирает точность матч.

3 голосов
/ 19 июля 2012

Чтобы избежать необходимости цитировать вручную:

#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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...