Defined in header <memoized_invoke.hh>

bool is_done() const noexcept;                       // (1)

auto const& value() const                            // (2)
    requires ( ! std::is_void_v< result_type > );

1) is_done()

Returns true once the callable has run to completion and a value is cached. Returns false:

  • before the first operator(),
  • after a reset(),
  • after the callable threw (the state was rolled back),
  • on a freshly copied or moved lock_free object (its state is re-initialised).

noexcept. Under lock_free it is a single acquire load; the value it returns is a snapshot and may be stale the instant it is read if another thread is mid-call.

2) value()

Returns a const reference to the cached result — without invoking the callable. Available only when result_type is not void.

Precondition: is_done() == true. If the precondition does not hold the behaviour is undefined; the shipped implementation throws std::bad_optional_access (it calls std::optional::value() on an empty optional).

value() returns a true reference into the object's storage — no copy — unlike operator(), which returns by value. Prefer value() when the result is large and you only need to read it.

Return value

is_done()bool
value()result_type const& (spelled auto const&)

Exceptions

  • is_done() — none (noexcept).
  • value()std::bad_optional_access if called when is_done() is false (undefined behaviour formally; this is what the implementation does).

Notes

There is no has_value() distinct from is_done() — for a non-void callable they are the same thing. For a void callable, is_done() is the only observer; there is no value.

value() is const, so it is safe to call on a memoized_invoke const& once you know it is done — a common pattern for a shared, load-once singleton:

inline Config const& config()
{
    static auto loader = make_memoized<lock_free>(&Config::load);
    loader();                 // first caller loads
    return loader.value();    // everyone gets the same reference
}

Example

#include <memoized_invoke.hh>
#include <iostream>
#include <stdexcept>

using fedem::utility::memoized_invoke;

int main()
{
    memoized_invoke co( [](int x){ return x * x; }, 8 );

    std::cout << std::boolalpha << co.is_done() << '\n';   // false
    try { (void) co.value(); }
    catch (std::bad_optional_access const&) { std::cout << "not ready\n"; }

    co();
    std::cout << co.is_done() << ' ' << co.value() << '\n'; // true 64
}

See also

  • operator() — returns by value; runs the callable if needed.
  • reset — after this, is_done() is false again.