Внутрянка инстанциаций шаблонов
Хочу в этом небольшом посте в явном виде продемонстрировать вам, что значит определение шаблона и его явная/неявная инстанциация. Сразу говорю, что буду использовать gcc в качестве компилятора.
Возьмем тот же пример с кораблем и оставим от него только хэдэр и сорец:
Сейчас в единице трансляции, соответствующей ship.cpp, есть только объявление и определение шаблона, больше ничего. Это значит, что никакого кода для этого юнита генерироваться не будет.
Проверим это с помощью утилитки nm, которая показывает символы бинарника. Скомпилируем ship.cpp в объектный файл и посмотрим, какие там символы есть внутри:
Как говорят математики: ЧТД и точка!
Теперь проверим неявную инстанциацию. Добавим в ship.cpp функцию:
Посмотрим теперь на символы этого юнита. Помимо всего прочего побочного непотребства, получим следующее:
Теперь мы имеем скомпилированную функцию foo и метод TurnShip класса Ship параметризованного строкой.
Для явной инстанциации уберем из ship.cpp функцию foo и добавим строчку:
и посмотрим на символы:
Как и ожидалось в принципе.
Вот поэтому-то при использовании подхода разделения шаблона на объявление в хэдэре и определение в сорце без явной инстанциации будет ошибка линковки. В единице трансляции, соответствующей определению шаблона, не будет никакого кода. Единицы трансляции на этапе компиляции не обмениваются информацией, поэтому компилятор не сможет инстанцировать шаблон на этом этапе. А на этапе линковки уже поздно смотреть на определение шаблона, потому что его просто не будет. Текст уберется, а кода никакого сгенерировано не будет. Как-то так.
Я не просто так вам это все рассказываю. Это нужно для понимания дальнейших постов.
Don't rely on words, check them. Stay cool.
#cppcore #template #compiler
Хочу в этом небольшом посте в явном виде продемонстрировать вам, что значит определение шаблона и его явная/неявная инстанциация. Сразу говорю, что буду использовать gcc в качестве компилятора.
Возьмем тот же пример с кораблем и оставим от него только хэдэр и сорец:
// ship.hpp
template<typename T>
struct Ship
{
// contain some fields
void TurnShip(T command);
};
// ship.cpp
#include "ship.hpp"
#include <string>
template <class T>
void Ship<T>::TurnShip(T command) {/* do stuff using command */}
Сейчас в единице трансляции, соответствующей ship.cpp, есть только объявление и определение шаблона, больше ничего. Это значит, что никакого кода для этого юнита генерироваться не будет.
Проверим это с помощью утилитки nm, которая показывает символы бинарника. Скомпилируем ship.cpp в объектный файл и посмотрим, какие там символы есть внутри:
nm ship.o
//Output
ship.o: no symbols
Как говорят математики: ЧТД и точка!
Теперь проверим неявную инстанциацию. Добавим в ship.cpp функцию:
void foo() {
Ship<std::string> ship{};
ship.TurnShip(std::string{"Turn upside down"});
}
Посмотрим теперь на символы этого юнита. Помимо всего прочего побочного непотребства, получим следующее:
nm ship.o
//Output
0000000000000000 T __Z3foov
0000000000000060 T __ZN4ShipINSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEE8TurnShipES6_
Теперь мы имеем скомпилированную функцию foo и метод TurnShip класса Ship параметризованного строкой.
Для явной инстанциации уберем из ship.cpp функцию foo и добавим строчку:
template struct Ship<std::string>;
и посмотрим на символы:
nm ship.o
//Output
0000000000000000 T __ZN4ShipINSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEE8TurnShipES6_
Как и ожидалось в принципе.
Вот поэтому-то при использовании подхода разделения шаблона на объявление в хэдэре и определение в сорце без явной инстанциации будет ошибка линковки. В единице трансляции, соответствующей определению шаблона, не будет никакого кода. Единицы трансляции на этапе компиляции не обмениваются информацией, поэтому компилятор не сможет инстанцировать шаблон на этом этапе. А на этапе линковки уже поздно смотреть на определение шаблона, потому что его просто не будет. Текст уберется, а кода никакого сгенерировано не будет. Как-то так.
Я не просто так вам это все рассказываю. Это нужно для понимания дальнейших постов.
Don't rely on words, check them. Stay cool.
#cppcore #template #compiler