callback function with no dynamic memory allocation
lambda's don't alloc, std::function only allocates memory if the object it is wrapping is 'too large'.  The VC++ 2019 std::function impl defines 'too large' as being more than 7 * sizeof(void*) bytes in size.  Other impl may use a different limit.  This is big enough to handle many (most ?) cases w/o allocating.

You could make your own function class, based on std::function, and put static_assert's in the constructors and assignment op's to ensure none of your code that uses your function would trigger an alloc; or if it would you could increase the 'too large' size of your function class.  This would give you something as flexible as std::function, and the control over alloc that you want.

[EDIT]

If you don't want to use the VC++ version, the gcc one is at:

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/std_function.h

To start you can copy the file and put static_assert's before lines 160 and 237 to catch any cases that would require an alloc (likely also have to check dependencies in other gcc .h files).

... it looks like this version doesn't reserve much space i.e. would alloc in many cases.  You'd have to make a couple other tweaks to increase the no_copy size.