This takes an arbitrary duration of the chronograph and breaks it into other duration values:
template<class...Durations, class DurationIn>
std::tuple<Durations...> break_down_durations( DurationIn d ) {
std::tuple<Durations...> retval;
using discard=int[];
(void)discard{0,(void((
(std::get<Durations>(retval) = std::chrono::duration_cast<Durations>(d)),
(d -= std::chrono::duration_cast<DurationIn>(std::get<Durations>(retval)))
)),0)...};
return retval;
}
Test code:
int main() {
auto then = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_for( std::chrono::seconds(3) );
auto now = std::chrono::high_resolution_clock::now();
auto duration = now - then;
auto clean_duration = break_down_durations<std::chrono::seconds, std::chrono::milliseconds, std::chrono::microseconds>( duration );
std::cout << std::get<0>(clean_duration).count() << "::" << std::get<1>(clean_duration).count() << "::" << std::get<2>(clean_duration).count() << "\n";
}
The formatting code can be cleared and inserted into the function.
Living example .
It would be fun to write autoformats for such a set of (increasing accuracy) duration.
, ::. , 10 setw . , .
, , std::size_t .count() .
:
template<class...Durations>
std::string format_durations( std::tuple<Durations...> d ) {
std::size_t values[]={(std::size_t)std::get<Durations>(d).count()...};
auto ratios = get_ratios<Durations...>();
std::stringstream ss << std::setfill('0');
ss << values[0];
for (std::size_t const& v:values) {
std::size_t i = &v-values;
if (i==0) continue;
ss << "::" << std::setw( log_10_round_up(ratios[i-1]) ) << values[i];
}
return ss.str();
}
log_10_round_up get_ratios .
hh: mm: ss - , .