Статический член шаблонного класса не создается, если на него не ссылаются

#include <iostream>

template <typename T>
class Temp {
 public:
  static Temp temp;
  Temp() { std::cout << "hi!"; }
};

// Definition.
template <typename T>
Temp<T> Temp<T>::temp;

Я создал простой класс шаблона. Я думал, что создания экземпляра объекта Temp достаточно для создания статического temp в Temp.

int main() {
  Temp<int> t;
}

Но это ответило только одним «привет!».

Принимая во внимание, что если я явно ссылаюсь на temp,

int main() {
  Temp<int> t;
  Temp<int>::temp;
}

он напечатал "привет!" два раза, и я мог подтвердить, что статический объект был создан во время его обычной инициализации (перед вызовом main). Каковы критерии компилятора для исключения построения статического объекта? Кроме того, как я могу обеспечить его соблюдение, кроме ссылки на него?

@dxiv есть ли какая-нибудь ссылка, которую я могу найти об этом?

Jaebum 23.12.2020 06:24

У вас нет под рукой стандарта, но посмотрите ссылку в конце вопроса Инициализация статического члена C++ (шаблон весело внутри). Исправление к моему первому (теперь удаленному) комментарию: статические элементы шаблона не создаются, если на них не ссылаются, или специализация явно объявлена.

dxiv 23.12.2020 06:28

Для работы шаблонов довольно важно, чтобы неиспользуемый код не создавался, например. такие вещи, как std::vector с некопируемым типом, работают до тех пор, пока вы не вызываете определенные методы

Alan Birtles 23.12.2020 08:12
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
3
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете явно создать экземпляр класса, чтобы повысить вероятность включения члена static без ссылки на него:

template class Temp<int>;

Обратите внимание, однако, что в зависимости от параметров компилятора/компоновщика код без ссылок не обязательно включается в окончательный двоичный файл. В частности, любая попытка зарегистрировать что-либо с помощью объекта обречена на провал! Например, для больших сборок довольно часто используются специальные разделы для функций и объектов, а компоновщики ELF будут включать только разделы, на которые есть ссылки.

Шаблон обычно создается только тогда, когда это необходимо. Обычно это означает, что на них есть ссылки («ODR-используется» в стандарте). Вы можете принудительно создать экземпляр с помощью явного создания, как показано выше. Однако даже после создания экземпляра компилятором компоновщик может удалить неиспользуемый код. Конечно, что-то, регистрирующее объект в некотором реестре, не является «неиспользуемым кодом» с вашей точки зрения, но это неиспользуемый код с точки зрения компоновщика. Компоновщик обычно работает с разделами, которые, в свою очередь, обычно основаны на файлах, но есть варианты, чтобы указать разделы или заставить компилятор генерировать более мелкие разделы, чтобы уменьшить размер исполняемого файла.

Другие вопросы по теме