访问时使用什么类型和storing/parsing std::chrono::duration::milliseconds (cpprest)
What type to use when accessing and storing/parsing std::chrono::duration::milliseconds (cpprest)
一个简化的例子:
//...
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;
}
}
//...
}
}
我的 class 包含一堆 std::chrono::milliseconds
字段,代表相应的延迟。我想将这些值存储在 class 的 JSON
表示中。
大多数 JSON
值仅适用于标准内部类型,但 std::chrono::milliseconds
实现 std::chrono::duration
模板。
它有一个 count()
方法,returns 一个数量的刻度作为 rep
类型的变量,在我的系统上是 typedef
到 long long
代码需要可移植。从实用的角度来看,将 count()
的结果转换为简单的 long 并将其传递给 JSON
库有多安全?
我是否正确实现了访问器(使用 unsigned long
类型)?
实际上,我通常将延迟值存储在 0 到 5000 的范围内,但是没有什么能阻止其他人编辑配置文件并在那里写入不正确的值,这可能会导致运行时错误和奇怪的行为。
P.S。需要明确的是——它不是 Rubber Duck 调试线程。我以前从未处理过 "might be very big" 值,而具有多个 libstdc++ 实现和 typedef 的 C++ 使它变得困难。我担心潜在的错误和陷阱。谢谢。
实际上,大多数 JSON 实现对所有数字都使用 64 位 IEEE 浮点数,也就是 C++ 中的 double
。
所以你有一点不匹配:C++ milliseconds
可以完全精确地存储 +/- 9e18,但是 JSON 数字可以存储 +/- 1.8e308(但只有 53 位精度)。
因此,如果您的 C++ 值超过 285 千年(2^53 毫秒),它将失去精度。看起来这对您的应用程序来说没有问题,因为值是 "delay" 并且没有人有时间这样做。如果您的 JSON 解析逻辑读取的值大于 INT64_MAX,它可能会抛出异常。
我建议定义您自己的持续时间类型 "double precision seconds"。然后可以将其提取为计数,并以清晰明确的含义传递给其他语言。一些示例代码(与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 是秒,但它是实数而不是整数,所以毫秒或其他任何东西都保留在十进制中。
一个简化的例子:
//...
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;
}
}
//...
}
}
我的 class 包含一堆 std::chrono::milliseconds
字段,代表相应的延迟。我想将这些值存储在 class 的 JSON
表示中。
大多数 JSON
值仅适用于标准内部类型,但 std::chrono::milliseconds
实现 std::chrono::duration
模板。
它有一个 count()
方法,returns 一个数量的刻度作为 rep
类型的变量,在我的系统上是 typedef
到 long long
代码需要可移植。从实用的角度来看,将 count()
的结果转换为简单的 long 并将其传递给 JSON
库有多安全?
我是否正确实现了访问器(使用 unsigned long
类型)?
实际上,我通常将延迟值存储在 0 到 5000 的范围内,但是没有什么能阻止其他人编辑配置文件并在那里写入不正确的值,这可能会导致运行时错误和奇怪的行为。
P.S。需要明确的是——它不是 Rubber Duck 调试线程。我以前从未处理过 "might be very big" 值,而具有多个 libstdc++ 实现和 typedef 的 C++ 使它变得困难。我担心潜在的错误和陷阱。谢谢。
实际上,大多数 JSON 实现对所有数字都使用 64 位 IEEE 浮点数,也就是 C++ 中的 double
。
所以你有一点不匹配:C++ milliseconds
可以完全精确地存储 +/- 9e18,但是 JSON 数字可以存储 +/- 1.8e308(但只有 53 位精度)。
因此,如果您的 C++ 值超过 285 千年(2^53 毫秒),它将失去精度。看起来这对您的应用程序来说没有问题,因为值是 "delay" 并且没有人有时间这样做。如果您的 JSON 解析逻辑读取的值大于 INT64_MAX,它可能会抛出异常。
我建议定义您自己的持续时间类型 "double precision seconds"。然后可以将其提取为计数,并以清晰明确的含义传递给其他语言。一些示例代码(与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 是秒,但它是实数而不是整数,所以毫秒或其他任何东西都保留在十进制中。