автоматическая инициализация библиотеки при запуске

У меня куча статики init() методы, которые мне нужно вызывать при запуске приложения. Вроде как надо делать:

A::init();
S::init();
//...

Один из способов сделать это — инициализировать статическую переменную следующим образом:

static bool const b{A::init(), S::init(), false};

Существуют ли более хорошие альтернативы?

2

Решение

Вы можете использовать экземпляр класса запуска, который инициализирует различные компоненты в своем конструкторе и завершает их в своем деструкторе. Пример:

struct Startup
{
Startup()
{
A::Init();
B::Init();
}
~Startup()
{
B::Term();
A::Term();
}
};

namespace { Startup startup; }

int main()
{
// do stuff being completely oblivious to the startup
}
3

Другие решения

Я несколько раз играл с «жизнью до начала», прежде чем понял, что это обычно более болезненно, чем необходимо.

Поэтому мой совет:

int main() {
A::init();
S::init();

// ...
}

Для ясности, возможно, стоит создать init функция, которая будет вызывать все эти по очереди.

И если дерево зависимостей между различными библиотеками не является кристально чистым, я советую против упаковка (т.е. имея B::init вызов A::init) потому что в случае алмазных зависимостей вы можете получить базовую библиотеку init вызывается несколько раз.

3

Не автоинициализировать. Явно инициализируйте ваши подсистемы во время запуска внутри вашего main,

Причины:

  1. Вы можете контролировать порядок инициализации
  2. Если инициализация не удалась, вы можете справиться с этим правильно
  3. Если инициализация приводит к сбою, вам будет проще отладить и, надеюсь, иметь правильную трассировку стека
  4. Это гарантирует, что вы полностью осведомлены о процессе инициализации
3

Вы можете иметь init_dispatch шаблон, который вызывает init() через список переменных аргументов:

template<typename T>
struct dispatch
{
dispatch() { T::init(); }
};

template<typename... Ts>
struct init_dispatch : std::false_type
, dispatch<Ts>...
{
init_dispatch() : dispatch<Ts>{}... {}
};

static bool const b = init_dispatch<A, S>{}.value;

демонстрация

1

Лично я бы настоятельно рекомендовал сделать это простым: инициализировать вещи в пределах mainне с волшебной статикой. Таким образом, ясно, что это происходит, и это явно когда такое случается. И вы можете рассуждать о состоянии приложения до и после него.

Все, что происходит до и после main как правило, могут привести к неприятностям в будущем.

1