Skip to content

Intermediate Gotchas

The Future You Can Get Only Once

reading the answer consumes the handle

int main() {
  std::promise<int> promise;
  auto result = promise.get_future();
  promise.set_value(42);

  std::cout << result.get() << '\n';
  try {
    std::cout << result.get() << '\n';
  } catch (const std::future_error& error) {
    std::cout << error.what() << '\n';
  }
}

Run it. Can the same std::future return its value twice?

Answer
42
std::future_error: No associated state

The first get() leaves the future with no state. The second call is undefined behavior; this output is typical, not guaranteed.

Why

std::future::get() retrieves the result and releases this future's association with its shared state, leaving valid() false. Calling any member other than the destructor, move assignment, share or valid on a future in that state is undefined behavior ([futures.unique.future]). The standard only recommends that implementations detect it and throw std::future_error with future_errc::no_state; libstdc++ does, which is why this run reports anything at all. Treat the message as typical — the wording is this library's, and a conforming implementation need not throw. GCC emits no warning under -Wall -Wextra.

The fix

Read the future once, then keep the ordinary value:

int answer = result.get();
use(answer);

Use std::shared_future when several readers genuinely need the same result.

Takeaway: get() consumes a std::future; save the value or use shared_future.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry