TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #218 3.31K
​Внутрянка инстанциаций шаблонов

Хочу в этом небольшом посте в явном виде продемонстрировать вам, что значит определение шаблона и его явная/неявная инстанциация. Сразу говорю, что буду использовать 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
  • 🔥 20
  • 👍 8
  • ❤ 3
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →