rmccabe3701
rmccabe3701

Reputation: 1468

non conforming return value for std::chrono::duration::operator%() in Microsoft C++ 2012

I'm in the process of porting some C++ code to Windows (from Linux/g++4.8.1) and I noticed that Microsoft's implementation of the duration's modulus operator is incorrect.

The simple program

#include <chrono>
#include <iostream>

using namespace std::chrono;

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

when compiled with Microsoft Visual Studio 2012 gives the compilation error:

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

The standard (http://en.cppreference.com/w/cpp/chrono/duration/operator_arith4) has the definition as

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 );

I.e. the modulus operator returns a duration of the common type. Microsoft's implementation (http://msdn.microsoft.com/en-us/library/hh874810.aspx) has the definition as

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);

This incorrectly returns the underlying duration storage type. Is this a bug, or am I missing something?

Upvotes: 2

Views: 558

Answers (1)

Howard Hinnant
Howard Hinnant

Reputation: 219345

Yes, this is a bug and the fix is available in Visual Studio 2015.

The reason it's an implementation bug comes from dimensional analysis.

Clearly if we subtract seconds from seconds the result is seconds.

seconds = seconds - seconds

And if we divide seconds by seconds, the result is a scalar (a scalar has no units).

scalar = seconds / seconds

And finally one can multiply seconds by a scalar and get seconds.

seconds = seconds * scalar
seconds = scalar * seconds

In [expr.mul]/p4 the standard defines the modulus operator:

... if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a ...

Said slightly differently:

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

So a duration % duration has the same units as:

seconds - (seconds/seconds)*seconds

which simplifies down to just seconds, and not a scalar.

The same analysis explains why:

seconds % scalar = seconds

Upvotes: 8

Related Questions