Влияние виртуального на использование члена класса шаблона
Я (смутно) знаю, что шаблон не создается, если он не используется. Например, следующий код скомпилируется нормально, хотя T::type
не имеет смысла, когда T = int
,
template<typename T>
struct A
{
void f() { using type = typename T::type; }
};
A<int> a; //ok
Компилируется потому что f()
не используется, поэтому он не создан - таким образом, действительностьT::type
остается непроверенным. Неважно, если какая-то другая функция- член g()
звонки f()
,
template<typename T>
struct A
{
void f() { using type = typename T::type; }
void g() { f(); } //Is f() still unused?
};
A<int> a; //ok
Это также составляет штрафы. Но здесь я осознаю неопределенность в моем понимании определения "использование". Я спрашиваю:
- Является
f()
все еще не используется? Как именно?
Я ясно вижу, как он используется внутри g()
, Но потом я подумал, так как g()
не используется, f()
также не используется, с точки зрения реализации. Это кажется достаточно разумным. до сих пор.
Однако, если я добавлю virtual
ключевое слово для g()
не компилируется:
template<typename T>
struct A
{
void f() { using type = typename T::type; }
virtual void g() { f(); } //Now f() is used? How exactly?
};
A<int> a; //error
Это приводит к ошибке компиляции, потому что теперь он пытается создать экземпляр f()
, Я не понимаю это поведение.
Кто-нибудь может объяснить это? Особенно влияние virtual
Ключевое слово по определению "использование" члена шаблона класса.
1 ответ
Беглый взгляд на 3.2 [basic.def.odr] дает:
3 / [...] Виртуальная функция-член используется odr, если она не является чистой. [...]
И я также нашел в 14.7.1 [temp.inst]:
10 / Реализация не должна неявно создавать экземпляр шаблона функции, шаблона элемента, не виртуальной функции-члена, класса-члена или статического члена данных шаблона класса, который не требует создания экземпляра. Не определено, будет ли реализация неявно создавать экземпляр виртуальной функции-члена шаблона класса, если в противном случае функция виртуального члена не была бы создана. (акцент мой)
Так что... я бы сказал, что virtual
метод всегда будет создан.
В прагматических терминах я бы ожидал, что компилятор создаст экземпляр виртуальной таблицы шаблонного класса при создании экземпляра класса; и, таким образом, немедленно создать все экземпляры virtual
функции-члены этого класса (поэтому он может ссылаться на функции из виртуальной таблицы).