Defined in header <memoized_invoke.hh>

template< typename ExecutionPolicy, typename F, typename... Args >
requires std::is_invocable_v< F, Args... >
auto make_memoized( F&& func, Args&&... args )
    -> memoized_invoke< ExecutionPolicy, std::decay_t< F >, std::decay_t< Args >... >;

CTAD for memoized_invoke always selects single_threaded (a deduction guide cannot be told which policy you want). make_memoized is how you ask for lock_free, or a custom policy, while still letting F and Args be deduced.

Template parameters

ParameterDescription
ExecutionPolicyThe policy for the returned object. Named explicitly — this is the whole point of the factory.
FDeduced from func. Perfect-forwarded, then stored as std::decay_t<F>.
Args...Deduced from args. Perfect-forwarded, then stored as std::decay_t<Args>....

Parameters

ParameterDescription
funcThe callable. Forwarded into the memoized_invoke constructor.
argsThe argument set. Forwarded, then decayed and stored by value.

Return value

A memoized_invoke<ExecutionPolicy, std::decay_t<F>, std::decay_t<Args>...> constructed from func and args.... Returned by value; typically bound with auto.

Exceptions

Whatever constructing the memoized_invoke throws — i.e. a throwing move of F or of a stored argument type. make_memoized itself adds nothing.

Notes

The requires std::is_invocable_v<F, Args...> clause matches the one on memoized_invoke; an incompatible func / args pairing is a compile error at the factory call.

For single_threaded you do not need the factory at all — the class-name form with CTAD is shorter:

memoized_invoke a( &f, 1, 2 );                          // single_threaded
auto            b = make_memoized<single_threaded>(&f, 1, 2);  // identical, verbose
auto            c = make_memoized<lock_free>(&f, 1, 2);        // the reason to use it

Example

#include <memoized_invoke.hh>
#include <cassert>

using fedem::utility::make_memoized;
using fedem::utility::lock_free;

double slow_pi() { /* ... */ return 3.14159265358979; }

int main()
{
    auto pi = make_memoized<lock_free>( &slow_pi );

    double a = pi();     // computes
    double b = pi();     // cached
    assert( a == b );
    assert( pi.is_done() );
}

See also