2

我正在将一些 C++ 代码移植到 Windows(来自 Linux/g++4.8.1),我注意到微软对持续时间的模运算符的实现是不正确的。

简单的程序

#include <chrono>
#include <iostream>

using namespace std::chrono;

int main(void)
{
    std::cout << (milliseconds(1050)%seconds(1)).count() << std::endl;
    return 0;
}

使用 Microsoft Visual Studio 2012 编译时会出现编译错误:

error C2228: left of '.count' must have class/struct/union

标准(http://en.cppreference.com/w/cpp/chrono/duration/operator_arith4)的定义为

template< class Rep1, class Period1, class Rep2, class Period2 >
typename common_type<duration<Rep1,Period1>, duration<Rep2,Period2>>::type
constexpr operator%( const duration<Rep1,Period1>& lhs,
    const duration<Rep2,Period2>& rhs );

即模运算符返回常见类型的持续时间。微软的实现(http://msdn.microsoft.com/en-us/library/hh874810.aspx)的定义为

template<class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<Rep1, Rep2>::type
operator%(
  const duration<Rep1, Period1>& Left,
  const duration<Rep2, Period2>& Right);

这会错误地返回基础持续时间存储类型。这是一个错误,还是我错过了什么?

4

1 回答 1

8

是的,这是一个错误,Visual Studio 2015 中提供了修复程序

它是一个实现错误的原因来自维度分析。

seconds显然,如果我们从seconds结果中减去seconds

seconds = seconds - seconds

如果我们除以secondsseconds结果是一个标量(标量没有单位)。

scalar = seconds / seconds

最后可以乘以seconds一个标量并得到seconds

seconds = seconds * scalar
seconds = scalar * seconds

在 [expr.mul]/p4 中,标准定义了模运算符:

...如果商a/b在结果的类型中是可表示的, (a/b)*b + a%b则等于a...

略有不同的说法:

a % b = a - (a/b)*b

所以 aduration % duration具有与以下相同的单位:

seconds - (seconds/seconds)*seconds

这简化为 just seconds,而不是标量。

同样的分析解释了原因:

seconds % scalar = seconds
于 2013-07-21T15:44:35.320 回答