Я только слышал, что люди используют термин «отложенное создание экземпляров» для обозначения ситуации, когда определение члена класса создается только в том случае, если оно используется
template<typename T>
struct A {
void f() {
T a; // invalid if T is void
}
};
A<void> a; // valid!
В этом случае A<void>
подразумевается неявносоздание экземпляра, потому что компилятору необходимо знать его размер (формально тип класса должен быть завершен, поэтому запускается реализация).Но создание его определений членов отложено до момента их фактического использования.Это относится не только к функциям-членам, но и к статическим элементам данных и вложенным классам
struct Print {
Print() { std::cout << "hello!"; }
};
template<typename T>
struct A {
static Print print;
};
template<typename T>
Print A<T>::print;
Теперь, даже если вы неявно создаете экземпляр A<T>
, сообщение не будет напечатано, пока вы явно не обратитесь к A<T>::print
и используйте это.Явное создание экземпляров не будет откладывать создание определений элементов, поэтому следующее всегда будет печатать сообщение
template struct A<void>;
Хотя существует хитрость для запуска создания определений элементов для неявных реализаций: обратитесь к ним в частях объявлениячлен класса, как в следующем измененном шаблоне класса
template<typename T, T&> struct useit { };
template<typename T>
struct A {
static Print print;
typedef useit<Print, print> useit_type;
};
Теперь, если неявно создается экземпляр A<T>
, печатается сообщение, потому что объявление typedef ссылается на него.