Рассмотрим этот пример кода:
template<class D>
char register_(){
return D::get_dummy(); // static function
}
template<class D>
struct Foo{
static char const dummy;
};
template<class D>
char const Foo<D>::dummy = register_<D>();
struct Bar
: Foo<Bar>
{
static char const get_dummy() { return 42; }
};
Я ожидал, что dummy
будет инициализирован, как только будет конкретный экземпляр Foo
, который у меня есть с Bar
. Этот вопрос (и стандартная цитата в конце) объяснен довольно ясно , почему этого не происходит.
[...] в частности, инициализация (и любые связанные с ней побочные эффекты) статического члена данных не происходит, если сам статический член данных не используется таким образом, который требует существования определения статического члена данных.
Есть ли способ принудительно dummy
инициализироваться (фактически вызывая register_
) без любого экземпляра Bar
или Foo
(без экземпляров, поэтому без обмана конструктора) и без пользователя Foo
нужно каким-то образом явно указать член? Дополнительные файлы cookie, чтобы производный класс ничего не делал.
Изменить: нашел способ с минимальным влиянием на производный класс:
struct Bar
: Foo<Bar>
{ // vvvvvvvvvvvv
static char const get_dummy() { (void)dummy; return 42; }
};
Хотя мне все равно хотелось бы, чтобы производный класс не делал этого. : |
Foo
. : / - person Xeo   schedule 21.06.2011static char const get_dummy() { (void)dummy; return 42; }
- Я сомневаюсь, что эта циклическая зависимость междуBar::get_dummy()
иFoo<Bar>::dummy
гарантированно работает (по стандарту). Похоже, трюк сильно зависит от реализации. Я ошибся? - person Serge Dundich   schedule 21.06.2011dummy
вget_dummy
- это, конечно, неинициализированный, но это не имеет значения. :) Я вообще-то им не пользуюсь. - person Xeo   schedule 21.06.2011Foo<Bar>::dummy
инициализируется? И что должно помешать компилятору оптимизировать оператор(void)dummy;
(который не имеет никакого эффекта). - person Serge Dundich   schedule 21.06.2011dummy
инициализироваться, потому что он используется, как указано. w.r.t. оптимизации, я должен это проверить. - person Xeo   schedule 21.06.2011get_dummy()
. Статические члены и глобальные переменные инициализируются либо перед первым операторомmain
, либо перед первым использованием любого объекта или функции, определенных в той же единице перевода, что и этот статический член или глобальная переменная. Таким образом, полностью разрешено вообще не инициализировать Foo ‹Bar› :: dummy, если вы не используете какие-либо объекты или функции из той же единицы трансляции, где создается специализация шаблона Foo. - person Serge Dundich   schedule 21.06.2011Foo<Bar>::dummy
. Может быть достаточно одногоstruct Bar: Foo<Bar> {...}
определения (это приведет к созданию экземпляра специализации Foo ‹Bar›). - person Serge Dundich   schedule 21.06.2011(void)dummy
, и звонок не будет: ideone.com/Kukds - person Xeo   schedule 22.06.2011dummy
, даже если вы добавляете(void)dummy
кBar::get_dummy()
. Результат для любой конкретной реализации вообще не аргумент. Стандартные операторы C ++ - это. - person Serge Dundich   schedule 22.06.2011get_dummy
хотя бы один раз? - person dragonxlwang   schedule 21.01.2021