std::chrono::duration_cast(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… std::chrono::duration_cast(3) ✨

okay bestie so this is a page from the C++ Standard Libary manual (yes that's how the manual spells it, don't come for me πŸ™ˆ), and honestly? it's a little baddie. Let's get into it. πŸŽ€


🌸 NAME 🌸

std::chrono::duration_cast β€” literally just std::chrono::duration_cast, no cap, that's the whole name πŸ’€


✨ Synopsis ✨

defined up in the header <chrono> 🫢

template< class ToDuration, class Rep, class Period >
constexpr ToDuration duration_cast( const std::chrono::duration<Rep,Period>& d );

(since C++11) β€” she's been iconic since day one πŸ‘‘

So what does she even do? She converts a std::chrono::duration into a duration of a different type, ToDuration. Glow-up for your time units πŸ’…

And the fine print, because there's always fine print:

  • The function does not participate in overload resolution unless ToDuration is a specialization of std::chrono::duration. Like, if it's not that, she simply doesn't show up. main character boundaries βœ‹
  • No implicit conversions are used. None. Zero. Nada. 🚫
  • Multiplications and divisions are avoided where possible β€” specifically if it's known at compile time that one or more parameters are 1. Efficiency queen ⭐
  • Computations are done in the widest type available, and converted as if by static_cast to the result type only when finished. So she does the messy math in private and only serves looks at the end πŸ’–

πŸ¦‹ Parameters πŸ¦‹

  • d β€” the duration to convert. that's it. that's the parameter. πŸ“

🌈 Return value 🌈

d, but converted to a duration of type ToDuration. same vibe, different unit, slay ✨


πŸ’œ Notes πŸ’œ

okay this part is important so pay attention bestie:

Sometimes you don't even need her. Casting between integer durations where the source period is exactly divisible by the target period (think hours to minutes, the classic) β€” or casting between floating-point durations β€” can be done with ordinary casts or implicitly via std::chrono::duration constructors. No duration_cast required. She's off duty, let her rest 😌

BUT. and this is a big but 🫦:

Casting from a floating-point duration to an integer duration is subject to undefined behavior when the floating-point value is NaN, infinity, or too large to be representable by the target's integer type. That's UB, bestie, actual UB, we do not play with that πŸ’€

Otherwise, casting to an integer duration is subject to truncation, just like any static_cast to an integer type. Bits get yeeted. That's the deal 🫢


🧚 Example 🧚

This example measures the execution time of a function. Lowkey useful, highkey cute. ⏱️

#include <chrono>
#include <iostream>
#include <ratio>
#include <thread>

void f()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

int main()
{
    const auto t1 = std::chrono::high_resolution_clock::now();
    f();
    const auto t2 = std::chrono::high_resolution_clock::now();

    // floating-point duration: no duration_cast needed
    const std::chrono::duration<double, std::milli> fp_ms = t2 - t1;

    // integral duration: requires duration_cast
    const auto int_ms =
    std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);

    // converting integral duration to integral duration of
    // shorter divisible time unit: no duration_cast needed
    const std::chrono::duration<long, std::micro> int_usec = int_ms;

    std::cout << "f() took " << fp_ms << ", or "
              << int_ms << " (whole milliseconds), or "
              << int_usec << " (whole microseconds)\n";
}

⭐ Possible output ⭐

f() took 1000.14ms, or 1000ms (whole milliseconds), or 1000000us (whole microseconds)

see how the floating-point one keeps the .14 and the integral ones don't? that's the truncation thing from Notes. she told you so πŸ’…


πŸ‘‘ See also πŸ‘‘

  • duration (C++11) β€” a time interval (class template) πŸ•°οΈ
  • time_point_cast (C++11) β€” converts a time point to another time point on the same clock, with a different duration (function template) 🎯
  • floor(std::chrono::duration) (C++17) β€” converts a duration to another, rounding down (function template) ⬇️
  • ceil(std::chrono::duration) (C++17) β€” converts a duration to another, rounding up (function template) ⬆️
  • round(std::chrono::duration) (C++17) β€” converts a duration to another, rounding to nearest, ties to even (function template) 🎲

and that's the whole page, bestie πŸ’– sourced straight from http://cppreference.com, dated 2024.06.10 β€” go forth and cast your durations responsibly, ily, mwah πŸ«Άβœ¨πŸŽ€

πŸ“¦ where this page comes from