2016-08-05 76 views
1

我正在尝试按如下方式使用计时持续时间,但如果我将该比率增加为高于std::ratio<1,50>的任何值,则会在编译期间引发error: no viable overloaded '-='时发生的错误elapsed -= tickeRate为什么不会减小chrono :: durations?

int main() 
{ 
    using clock = std::chrono::high_resolution_clock; 
    using seconds = std::chrono::seconds; 

    std::chrono::duration<long long, std::ratio<1,20>> tickRate(1); 
// std::chrono::duration<long long, std::ratio<1,60>> tickRate(1); 

    clock::time_point start, stop; 

    start = clock::now(); 
    std::this_thread::sleep_for(seconds(1)); 
    stop = clock::now(); 

    clock::duration elapsed = stop - start; 

    int i = 0; 
    while (elapsed >= tickRate) 
    { 
     elapsed -= tickRate; 
     i++; 
    } 

    std::cout << "ticked " << i << " times." << std::endl; 

    return 0; 
} 

第一个问题是,为什么它只在tickRate> 1/50时抛出错误?第二,我可以研究什么课题,以便我可以通过未来的问题推理?

编辑:

编译器版本是:苹果LLVM 7.0.2版(铛-700.1.81)

此外,该实际工作有更小的数字,但不能肯定它。对我来说,1/51 .. 1/99失败,但是1/100开始再次正常工作。我尝试过双打,并且1/2500,1/3600扔同样的错误。现在我更加困惑。

+0

在我的机器上它可以很好地适用于'100','200'和'1000'。可能这个比例应该可以被一些数字整除。 – alexeykuzmin0

+0

你的编译器是什么? – rustyx

+0

似乎是这样。自从失败后,我从未超过60岁,但在您说出这一点之后,我尝试了不同的较小值。我会更新这个问题。谢谢。 – stewsims

回答

3
template< class Rep2, class Period2 > 
constexpr duration(const duration<Rep2,Period2>& d); 
(4) (since C++11) 

通过的std ::计时:: duration_cast(d).Count之间的转换d为适当的时间段和 滴答计数,仿佛构造一个持续时间()。 为了防止在转换过程中截断,则此构造 如果没有溢出由 转换诱导并仅参与重载解析:

(1)std::chrono::treat_as_floating_point<rep>::value == true

或两者:

(2)std::ratio_divide<Period2, period>::den == 1 , 和 std::chrono::treat_as_floating_point<Rep2>::value == false。 (即, 任一持续时间使用浮点蜱,或PERIOD2正是 整除周期)

在这种情况下,elapsed类型是std::chrono::duration<long long, std::ratio<1,20>>,而的tickRatestd::chrono::high_resolution_clock::duration,其std::chrono::duration<long int, std::ratio<1l, 1000000000l>>在我的amd64 GCC6.1上。

当您在elapsed上执行-=操作时,编译器会尝试将tickRate转换为相同类型的elapsed本身。

因为long long不是浮点类型,所以第2条适用于这种情况。 此转换仅在您的分母可以整除std::high_resolution_clock::period.den时有效。

+0

尽管你在'elapsed' /'tickRate'上颠倒了类型,这是有道理的。后续问题是 - 处理这个问题的最佳方法是什么?如果我的编译器/系统上的时钟持续时间不可分,但是它在你的上 - 我怎么能提前知道?我做的测试只是提前'duration_cast (tickRate)',有没有更好的方法? – stewsims

+0

@stewsims:这里(http://howardhinnant.github.io/duration_io/chrono_util.html)是一些你可以使用的实用工具,如果你想在非零方向截断(这是'duration_cast'的作用) 。 –

5

要从另一个duration减去一个,你应该确保他们的周期是等分的。这里:

elapsed -= tickRate; 

尝试从clock::duration减去std::chrono::duration<long long, std::ratio<1,60>>(这是在第二时间间隔1/60),其是(至少在MSVC++ 2015)等于std::chrono::duration<long long, std::ratio_multiply<std::ratio<100,1>,std::nano>>这恰好是100 ns

总结起来,这里的问题是1/60 s不是整数倍的间隔100 ns