限制 boost::options_description 中默认值的 std::cout 精度

发布于 2024-08-10 19:59:18 字数 622 浏览 14 评论 0原文

当我构造一个 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;

这仍然导致相同的输出:/

您对如何将默认值的显示限制在更少的位置有什么想法吗?

此致, 基督教

When I construct a boost::options_description instance like

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

and later want to have the automated output of the options that are available for my program, and put

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

the default value 0.2 is shown with way too high precision, which effectively clutters my output when I have long variable names:

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

unfortunately, a prior call to std::cout.precision did not help:

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

this leads still to the same output :/

Do you have any ideas on how to limit the display of the default value to less positions?

Best regards,
Christian

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜味超标? 2024-08-17 19:59:18

来自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,并提供构造from 并强制转换为 double,以及您自己的 ostream&运算符<< 与您想要的格式完全相同。但是,我不建议使用这种方法,除非您正在编写一个需要通用性的库。

来自 Boost Lexical Cast 的注释:

之前版本的 lexical_cast
使用默认流精度
读取和写入浮点数
数字。对于具有
相应的专业
std::numeric_limits,当前
版本现在选择精度
匹配。

From 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;
    }

So the implementation is dead simple (never a sure thing with Boost!). Trying to reconfigure your ostream to make the formatting come out as you want won't work, because the default value just gets converted to a string in a standalone ostringstream (inside lexical_cast).

So a simple workaround is to add your desired string representation as a second argument to default_value. Then you can make it print however you want (including not at all, if you pass an empty string). Like so:

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

The more "enterprisey" way to accomplish the same thing would be to implement your own type which would wrap double, be used for config.my_double, and provide construction from and coercion to double, and your very own ostream& operator<< with exactly the formatting you desire. I don't suggest this approach, however, unless you're writing a library that demands generality.

From the Boost Lexical Cast notes:

The previous version of lexical_cast
used the default stream precision for
reading and writing floating-point
numbers. For numerics that have a
corresponding specialization of
std::numeric_limits, the current
version now chooses a precision to
match.

独自唱情﹋歌 2024-08-17 19:59:18

为了避免手动引用:

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

To avoid having to quote by hand:

#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))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文