Мы все знаем, шаблон класса C++ не создает функции-члены, которые не используются, как показано на рисунке ниже:Полный экземпляр шаблона, принудительный в наложении шаблона C++?
template<typename T>
class A
{
public:
void WrongFunction(T t);
void RightFunction(T t);
};
template<typename T>
void A<T>::WrongFunction(T t)
{
std::vector<T> v;
auto a = "abc" - v;
}
template<typename T>
void A<T>::RightFunction(T t)
{
std::cout << "Success" << std::endl;
}
int main()
{
A<int> a;
a.RightFunction(2);
//a.WrongFunction(1);
return 0;
}
Поскольку WrongFunction не вызывается в основном, нет никакого фактического кода, генерируемого для него, и, следовательно, нет компиляции возникает ошибка.
Теперь давайте введем абстрактный базовый класс, который определяет интерфейс для класса А (в основном, наследования шаблонов):
template<typename T>
class Base
{
public:
virtual void RightFunction(T t) = 0;
virtual void WrongFunction(T t) = 0;
};
template<typename T>
class A : Base<T>
{
public:
void WrongFunction(T t) override;
void RightFunction(T t) override;
};
template<typename T>
void A<T>::WrongFunction(T t)
{
std::vector<T> v;
auto a = "abc" - v;
}
template<typename T>
void A<T>::RightFunction(T t)
{
std::cout << "Success" << std::endl;
}
int main()
{
A<int> a;
a.RightFunction(2);
//a.WrongFunction(1);
return 0;
}
Неожиданно компилятор отказывается работать:
prog.cc: In instantiation of 'void A::WrongFunction(T) [with T = int]': prog.cc:39:1: required from here prog.cc:24:20: error: no match for 'operator-' (operand types are 'const char [4]' and 'std::vector >') auto a = "abc" - v;
Мое понимание рабочего потока, в основном, я говорю, создавая экземпляр A. Fine, тогда компилятор находит объявление шаблона для A (обратите внимание, что A не является классом, A<SomeType>
is.). Ничего себе, это зависит от Base<int>
. Хорошо, компилятор затем находит объявление шаблона для Base, подключает int к позиции, удерживаемой T, - теперь у нас есть объявление для класса Base<int>
, но определение не создается - ведь мы не предоставили шаблон для генерации определения для Base<SomeType>
, и никто никогда не создавал ни одного экземпляра Base<int>
или вызывал функцию в экземпляре. Хорошо. Затем компилятор расширяет объявление Base<int>
и генерирует объявление A<int>
. Подождите, на следующей строке вызывается RightFunction. Таким образом, компилятор находит определение шаблона для RightFunction для A и подключает определенный тип int и генерирует определение функции-члена для A.
Поскольку WrongFunction никогда не вызывается (никакая специализация не задействована ни в одном явном экземпляре), компилятор не должен даже пытаться генерировать код для A<int>
:: WrongFunction --- мой вопрос в том, что происходит, черт возьми?
Компилятор: GCC 4.9.2
Спасибо.
Ну, вам нужно иметь адрес, который вы можете поместить в виртуальную таблицу. Так что да, я очень занят, чтобы найти это в стандарте, но методы должны быть скомпилированы, чтобы иметь адрес. –