I'm not informed of the Postgres's internals, but, maybe, that can be solved by grouping threads into different processes depending on which set of extensions they request.
void DoSomething(void* p, size_t numBytes);
Presuming p to mean a buffer of bytes, the direct declaration equivalent using span would be: void DoSomething(std::span<std::uint_8> /* or std::span<char> */ p);
No templated logic in header files necessary. The only template instantion is std:span, which, in theory, should already be used in most files. The author argues this still makes the code more complex, because of the need of reinterpret_cast, but does it actually?