Это связано с how C++ templates work. Поскольку компилятор не знает, что такое tmp
, пока вы не вызовете функцию (точнее, при ее создании), она не знает, как писать для нее код. Например, рассмотрим следующий шаблон:
template <typename T>
T add(T left, T right) {
return left + right;
}
Если T
является целым числом, то тело функции является целым числом добавить. Если T
- это двойной, это добавление с плавающей запятой. Если T
- std::string
, это вызов функции для std::string::operator+
.
Поскольку в любой программе на C++ существует много типов, и многие из них могут быть добавлены, и почти каждый из них добавляется по-разному, он не может создать код для функции до тех пор, пока он не узнает этот тип. Если он попытается сделать это для всех возможных типов T
, вы получите комбинаторный взрыв возможных реализаций, почти все из которых никогда не используются. Ваше время компиляции и двоичный размер были бы огромны, если бы не было никакой пользы.
Вещи немного сложнее с class templates. Для экземпляра шаблона класса фактически не нужно создавать экземпляры всех функций, если они не вызываются. Возвращаясь к нашему примеру, если мы вместо этого написал:
template <typename T>
class Adder {
T add(T left, T right) {
return left + right;
}
};
Adder<int> a;
это еще бы не экземпляр Adder<int>::add
даже если компилятор имеет всю информацию, чтобы знать, что add<int>
потенциально интересен, потому что вы не на самом деле вызовите или иным образом создайте экземпляр.
Это не функция * шаблона *. Это шаблон * функции *. Это не функция, а план будущей функции. Это совершенно несущественно.'func' будет * функцией шаблона *, то есть шаблоном * функции * со всеми уже известными параметрами шаблона. Это * создает экземпляр * шаблона, заставляя его «материализоваться». –
AnT