Other answers already mentioned that call_once effect may be achieved with magic static, or with mutex usage.
I want to focus on performance and corner case handling.
Using mutex will be slower than call_once on fast path (when the target function is already called). That's because mutex acquisition/release will be atomic RMWs, whereas call_once queries are just reads. You can fix mutex performance by implementing double-check lock, but this will complicate the program.
Using call_once is also safer than mutex, if the target function is first attempted to be called only on program exit. mutex isn't necessarily trivially destructible, so a global mutex may be destroyed by the time the target is to be called.
Magic static is also likely to be fast on fast path by making only reads to query if the object is already initialized. The performance of magic static vs call_once may depend on implementation, but generally magic static has more opportunity for the optimization, as it doesn't have to expose the state in a variable and has to be implemented by the compiler rather than only in the library.
MSVC specific: magic statics employ thread-local storage. This is more optimal than call_once. But magic static support can be turned off by /Zc:threadSafeInit-. The ability to turn it off is due to some thread-local storage disadvantages. call_once cannot be turned off. Before Visual Studio 2015, call_once wasn't implemented well, and magic statics weren't implemented at all, so it was hard to get one-time initialization without 3rd party libs.