16

假设我们有

#include <chrono>
#include <iostream>
#include <ctime>

namespace Ratios { typedef std::ratio<60*60*24,1> Days; }

typedef std::chrono::system_clock Clock;
typedef Clock::time_point TimePoint;

我们的main样子

int main(int argc, char *argv[])
{
    // argc check left out for brevity
    const Clock::rep d = static_cast<Clock::rep>(std::atoi(argv[1]));
    // Right now
    TimePoint now = Clock::now();
    // Start with zero days
    auto days = std::chrono::duration<Clock::rep, Ratios::Days>::zero();

    // Now we'd like to add d to the days
    days += d; // Error!
    days.count() = d; // Error!
    days = days + d; // Error!
    days += std::chrono::duration<Clock::rep, Ratios::Days>(d); // Okay
    days = days + std::chrono::duration<Clock::rep, Ratios::Days>(d); // Okay

    days *= d; // Why is this okay?
    days %= d; // And this too?

    TimePoint later = now + days;

    return 0;
}

禁止用户直接操作 a 的原因是什么duration

4

4 回答 4

24

这样做是为了强制您坚持使用强类型值而不是任意值。

Bjarne Stroustrup 在“The C++ Programming Language”(第 4 版,35.2.1,第 1011 页)中有关于此行为的示例:


"周期是一个单位系统,所以没有=+=取一个简单的值。允许这就像允许将5一个未知的 SI 单位添加到以米为单位的长度。考虑:

duration<long long, milli> d1{7}; // 7 milliseconds
d1 += 5; // error
[...]

5在这里意味着什么?5秒?5 毫秒?[...] 如果您知道自己的意思,请明确说明。例如:

d1 += duration<long long, milli>{5}; //OK: milliseconds"

于 2013-07-18T20:39:31.627 回答
13

其基本原理是保持所duration代表的时间单位的完整性。

您可以将rep视为无单位。但是duration它有一个时间单位。可以从秒中添加和减去秒。但是如果不使表达式模棱两可并且违反单位代数,就不能添加秒和无单位量。

话虽如此,可以将一个时间单位乘以一个标量(无单位),结果仍然是一个时间单位。该库仅表示时间单位的一次幂或零幂。升到零次方的时间单位是一个标量,用 表示rep。时间单位也可以有 2 或更多的幂,以及负幂。然而,这个库并不代表这样的单位。

两个量相加时,单位必须相同。

当两个量相乘或相除时,形成一个新的单位(例如公里/小时)。当相同单位的数量相乘时,它们的指数相加(例如 sec * sec == sec^2)。当相同单位的数量相除时,减去它们的指数(例如 sec / sec == sec^0 == 一个标量)。

std::chrono::duration库是物理量库的一致子集,它仅处理时间单位和指数等于 0 和 1 的时间单位。

于 2013-07-18T20:39:35.300 回答
8
days += d; // Error!

这是因为变量days以 86,400 秒为单位,而变量d是无单位的。将一个单位的数量添加到无单位标量的结果在标准尺寸分析中没有定义。

days *= d; // Why is this okay?
days %= d; // And this too?

因为用无单位的标量乘除数量并不是没有意义的。将 2 秒乘以 2 得到 4 秒。

考虑将 2 秒乘以 3 秒;结果是一个数量 6,单位为“秒平方”。当然chrono::duration不是一个完整的单位库,所以你不能拥有像时间平方这样的单位,但是像 boost.units 这样的库会支持它。

于 2013-07-18T20:42:06.870 回答
1

我假设这样做是为了迫使您考虑要添加/减去的持续时间单位是什么。它还可以防止您对时钟滴答的单位做出任何假设。

于 2013-07-18T20:31:09.147 回答