Why acts std::chrono::duration::operator*= not like built-in *=?

  • A+

As described in std::chrono::duration::operator+= the signature is

duration& operator*=(const rep& rhs); 

This makes me wonder. I would assume that a duration literal can be used like any other built-in, but it doesn't.

#include <chrono> #include <iostream>  int main() {     using namespace std::chrono_literals;     auto m = 10min;     m *= 1.5f;     std::cout << " 150% of 10min: " << m.count() << "min" << std::endl;      int i = 10;     i *= 1.5f;     std::cout << " 150% of 10: " << i << std::endl; } 

Output is

150% of 10min: 10min 150% of 10: 15 

Why was the interface choosen that way? To my mind, an interface like

template<typename T>  duration& operator*=(const T& rhs); 

would yield more intuitive results.

EDIT: Thanks for your responses, I know that the implementation behaves that way and how I could handle it. My question is, why is it designed that way.

I would expect the conversion to int take place at the end of the operation. In the following example both operands get promoted to double before the multiplications happens. The intermediate result of 4.5 is converted to int afterwards, so that the result is 4.

int i = 3; i *= 1.5; assert(i == 4); 

My expectation for std::duration would be that it behaves the same way.


The issue here is

auto m = 10min; 

gives you a std::chrono::duration where rep is a signed integer type. When you do

m *= 1.5f; 

the 1.5f is converted to the type rep and that means it is truncated to 1, which gives you the same value after multiplication.

To fix this you need to use

auto m = 10.0min; 

to get a std::chrono::duration that uses a floating point type for rep and wont truncate 1.5f when you do m *= 1.5f;.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: