std::future::get(3)

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

πŸ’– std::future::get(3) πŸ’–

okay so bestie, we're in the C++ Standard Libary man pages and today's main character is std::future::get β€” yes that get, the one everyone's been waiting for (literally, she waits). pull up a chair 🫢


✨ SYNOPSIS ✨

here's the whole cast, three overloads, all of them iconic since C++11:

Main template

T get();                         (1) (since C++11)

std::future<T&> specializations

T& get();                        (2) (since C++11)

std::future<void> specialization

void get();                      (3) (since C++11)

🌸 DESCRIPTION 🌸

so the get member function waits (like, by actually calling wait(), no shortcuts) until the shared state is ready, and then retrieves the value stored in the shared state (if there even is one, iykyk). and the second you call this function? valid() is false. gone. done. that's her arc 😭

⚠️ if valid() is false before the call to this function, the behavior is undefined. no cap, undefined. do not do this.

πŸŽ€ RETURN VALUE πŸŽ€

  • 1) the value v stored in the shared state, as std::move(v). slay, moved.
  • 2) the reference stored as value in the shared state.
  • 3) (none) β€” yeah she gives you nothing and honestly that's fine πŸ’…

πŸ”₯ EXCEPTIONS πŸ”₯

if an exception was stored in the shared state referenced by the future (like, say, via a call to std::promise::set_exception()) then that exception will be thrown. so get() can absolutely jump scare you. be ready. πŸ’€


⭐ NOTES ⭐

the C++ standard recommends that implementations detect the case when valid() is false before the call and throw a std::future_error with an error condition of std::future_errc::no_state. so they're encouraged to catch you being chaotic, but it's a recommendation, not a promise. πŸ™ˆ


πŸ¦‹ EXAMPLE πŸ¦‹

// Run this code

#include <chrono>
#include <future>
#include <iostream>
#include <string>
#include <thread>

std::string time()
{
    static auto start = std::chrono::steady_clock::now();
    std::chrono::duration<double> d = std::chrono::steady_clock::now() - start;
    return "[" + std::to_string(d.count()) + "s]";
}

int main()
{
    using namespace std::chrono_literals;

    {
        std::cout << time() << " launching thread\n";
        std::future<int> f = std::async(std::launch::async, []
        {
            std::this_thread::sleep_for(1s);
            return 7;
        });
        std::cout << time() << " waiting for the future, f.valid() = "
                  << f.valid() << '\n';
        int n = f.get();
        std::cout << time() << " f.get() returned " << n << ", f.valid() = "
                  << f.valid() << '\n';
    }

    {
        std::cout << time() << " launching thread\n";
        std::future<int> f = std::async(std::launch::async, []
        {
            std::this_thread::sleep_for(1s);
            return true ? throw std::runtime_error("7") : 7;
        });
        std::cout << time() << " waiting for the future, f.valid() = "
                  << f.valid() << '\n';

        try
        {
            int n = f.get();
            std::cout << time() << " f.get() returned " << n
                      << ", f.valid() = " << f.valid() << '\n';
        }
        catch (const std::exception& e)
        {
            std::cout << time() << " caught exception " << e.what()
                      << ", f.valid() = " << f.valid() << '\n';
        }
    }
}

Possible output:

[0.000004s] launching thread
[0.000461s] waiting for the future, f.valid() = 1
[1.001156s] f.get() returned with 7, f.valid() = 0
[1.001192s] launching thread
[1.001275s] waiting for the future, f.valid() = 1
[2.002356s] caught exception 7, f.valid() = 0

πŸ’œ DEFECT REPORTS πŸ’œ

so the following behavior-changing defect reports got applied retroactively to previously published C++ standards (yes, time travel, we love to see it βŒ›):

  • LWG 2096 β€” applied to C++11: behavior as published was that overload (1) needed to check whether T is MoveAssignable; correct behavior is that it's not required.

🌈 SEE ALSO 🌈

  • valid β€” checks if the future has a shared state (public member function) πŸ‘‘

alright bestie that's the whole page, go forth and get() responsibly πŸ’–βœ¨πŸŽ€

🧚 source + version + date, as promised: straight from http://cppreference.com, the 2024.06.10 drop of the C++ Standard Libary pages β€” page std::future::get(3), mwah 😘
πŸ“¦ where this page comes from