One thing call_once does for you is handle exceptions. That is, if the first thread into it throws an exception inside the functor (and propagates it), call_once will not satisfy call_once . A subsequent call is allowed to enter the functor again, trying to complete it without exception.
In your example, the exception case is also handled properly. However, it is easy to imagine a more complex functor where the exceptional case will not be properly handled.
All this suggests that call_once redundant with the call_once -statics function. For instance:.
CSingleton& CSingleton::GetInstance() { static std::unique_ptr<CSingleton> m_instance(new CSingleton); return *m_instance; }
Or easier:
CSingleton& CSingleton::GetInstance() { static CSingleton m_instance; return m_instance; }
The above is equivalent to your call_once example, and imho is simpler. Oh, apart from the order of destruction, it is very subtly different from this and your example. In both cases, m_instance destroyed in the reverse order of construction. But the construction order is different. In your m_instance built in relation to other objects with a local-local area in the same translation unit. Using the m_instance -statics function, m_instance is created when m_instance is executed.
This difference may or may not be important for your application. I usually prefer the function-locally-static solution, as it is "lazy". That is, if the application never calls GetInstance() , then m_instance never created. And there is no time during the launch of the application, when many statics are trying to build right away. You pay for the construction only in actual use.
source share