【问题标题】:What type to use when accessing and storing/parsing std::chrono::duration::milliseconds (cpprest)访问和存储/解析 std::chrono::duration::milliseconds (cpprest) 时使用什么类型
【发布时间】:2018-02-09 15:38:01
【问题描述】:

一个简化的例子:

//...

std::chrono::milliseconds _delay; //field in question

unsigned long getDelay() const
{
    return _delay.count();
}

void setDelay(unsigned long delay)
{
    _delay = std::chrono::milliseconds(delay);
}

json::value toJson() const
{
    using namespace web;
    json::value obj;
    obj[delay] = json::value::number(_delay.count());

    return obj;
}

bool fromJson(web::json::value value)
{
    for (auto it = value.as_object().cbegin(); it != value.as_object().cend(); ++it)
    {
        const std::string& str = it->first;
        const json::value& v = it->second;

        if (str == "delay")
        {
            if (v.is_integer())
            {
                _id = v.as_number().to_uint64(); //was v.as_integer(); - thx Nicol Bogas
                continue;
            }
            else
            {
                return false;
            }
        }

        //...
    }
}

我的课程包含一堆std::chrono::milliseconds 字段,它们代表相应的延迟。我想将这些值存储在类的JSON 表示中。 大多数JSON 值仅使用标准内部类型操作,但std::chrono::milliseconds 实现std::chrono::duration 模板。 它有一个count() 方法,该方法将刻度数量作为rep 类型的变量返回,在我的系统上是typedeflong long

代码必须是可移植的。从实际的角度来看,将count() 的结果转换为简单的 long 并将其传递给JSON 库有多安全? 我是否正确实现了访问器(使用unsigned long 类型)? 在实践中,我通常将延迟值存储在 0 到 5000 的范围内,但没有什么能阻止其他人编辑配置文件并在那里写入不正确的值,这可能会导致运行时错误和奇怪的行为。

附:只是要清楚 - 这不是橡皮鸭调试线程。我以前从未处理过“可能非常大”的值,而具有多个 libstdc++ 实现和 typedef 的 C++ 使其变得困难。我担心潜在的错误和陷阱。谢谢。

【问题讨论】:

  • 我认为更好的问题是as_integer 返回什么?这比long 的大小更可能是一个限制。
  • 必须转换吗?你不能把它存储为long long吗?
  • @NicolBolas 是的,我重新检查了source,发现它返回了int。我已将其更改为 v.as_number()v.as_number().to_uint64()
  • @CorellianAle,这真的没什么用。它仍然首先通过可能较小的类型。
  • @A.A:规范是第一个数字可以是 1-9,而不是最多 9 个数字。可能超过 9 位。

标签: c++ json c++11 chrono cpprest-sdk


【解决方案1】:

我建议定义您自己的持续时间类型“双精度秒”。然后可以将其提取为计数,并以清晰明确的含义传递给其他语言。一些示例代码(与json无关):

 TimePoint nowTime(std::chrono::system_clock::now());
 typedef std::chrono::duration<double>       FSeconds;
 FSeconds delta = std::chrono::duration_cast<FSeconds>(nowTime - startTime);
 ofs << "@" << std::fixed << delta.count() //...

所以这里的 delta.count 是秒,但它是实数而不是整数,所以毫秒或其他什么都保留在十进制中。

【讨论】:

    【解决方案2】:

    实际上,大多数 JSON 实现对所有数字都使用 64 位 IEEE 浮点数,即 C++ 中的 double

    所以你有一点不匹配:C++ milliseconds 可以存储 +/- 9e18 完全精度,但 JSON 数字可以存储 +/- 1.8e308(但只有 53 位精度)。

    因此,如果您的 C++ 值超过 285 千米(2^53 毫秒),它将失去精度。看起来这对您的应用程序来说没有问题,因为该值是“延迟”并且没有人有时间这样做。如果您的 JSON 解析逻辑读取的值大于 INT64_MAX,它可能会简单地抛出异常。

    【讨论】:

      猜你喜欢
      • 2023-01-11
      • 2016-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-03
      相关资源
      最近更新 更多