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
| Parameter | Description |
|---|---|
ExecutionPolicy | The policy for the returned object. Named explicitly — this is the whole point of the factory. |
F | Deduced 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
| Parameter | Description |
|---|---|
func | The callable. Forwarded into the memoized_invoke constructor. |
args | The 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
- memoized_invoke — the type this returns.
- deduction guides — the CTAD path,
single_threadedonly. - lock_free — the policy you most often reach for this to get.

