Reputation: 1468
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
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 toa
...
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