Я не могу ответить на вопрос напрямую.Я могу только быть настолько смелым, чтобы советовать, что это не «чистый C ++» код.Я использую следующее всякий раз, когда мне нужно «сделать это один раз и только один раз» стандартным C ++, кодирование идиома:
// header only
// never anonymous namespace
namespace my_space
{
inline single_thing_type const & make_once
( /* if required arguments for initializaton go here */ )
{
auto initor_ = [&](){
/* this is where it is made */
static single_thing_type single_instance ;
/*
or calling some non-default ctor, or some factory
and doing whatever is required by single_thing_type
to be made and initialised
*/
return single_instance ;
};
/* this is resilient in presence of multiple threads */
static single_thing_type const & singleton_ = initor_() ;
/*
return by ref. so type can be
non-movable and non-copyable
if required
*/
return singleton_ ;
}
// here we can provide a process-wide global if required
inline single_thing_type const &
single_global_made_once = make_once () ;
} // my_space
Есть много вариантов, но это ядро идиомы.Я уверен, что это может быть применено в контексте стандарта C ++, используя Qt.
Не приведенный ниже код Qt, используется упрощенная, все еще правильная версия вашего класса Foo сверху:
namespace my_space
{
struct Foo {
Foo()
{
std::cout << "Foo() ctor called.\n";
}
}; // Foo
inline Foo const & make_once ( )
{
auto initor_ = [&](){
static Foo single_instance ;
return single_instance ;
};
static Foo const & singleton_ = initor_() ;
return singleton_ ;
}
inline Foo const &
single_global_foo_made_once = make_once () ;
} // my_space
int main ()
{
using namespace my_space;
auto const & it_is_already_made
= single_global_foo_made_once ;
}
Я не утверждаю, что изобрел это.Хороший обзор и подробности смотрите здесь .Эта идиома не требует, чтобы обрабатываемый тип был изменен каким-либо образом.Возможно, вы можете попробовать это на нужных вам типах Qt.
То, чего нет в так называемом «Scot Meyers Singleton», - это использование лямбда-выражения («initor» выше).Хорошим вариантом использования является создание отдельного экземпляра какого-либо event_log.
inline event_log const & const & make_event_log_once ( )
{
auto initor_ = [&](){
auto event_log_file_name
= read_it_from_environemnt_confif_or_whatever() ;
auto event_log_file_path
= ensure_platform_and_folder (event_log_file_name ) ;
return event_log( event_log_file_path ) ;
};
static event_log singleton_{ initor_() } ;
return singleton_ ;
}
inline event_log const &
event_log_instance = make_event_log_once () ;
Прежде чем мы создадим экземпляр класса журнала событий, нам нужно как-то и откуда-то получить имя файла.Затем нам нужно указать полный путь к нему, убедившись, что платформа правильная, а папка на этой платформе гарантирована.Именно тогда мы можем сделать экземпляр event_log.Это то, что мы делаем в initor
лямбде, зная, что все это будет вызываться только один раз.
Наслаждайтесь стандартом C ++