Кратко:
Инстанцирование функций-членов шаблонного класса происходит при их использовании. Компилятор генерирует конкретный код для функций-членов при компиляции, основываясь на типах, переданных шаблону.
Виды инстанцирования
- Неявное инстанцирование: происходит автоматически при использовании шаблонного класса или его функций.
- Явное инстанцирование: может быть использовано для оптимизации и сокращения времени компиляции, когда шаблон используется многократно с одним и тем же типом.
Разделение реализации и определения
Шаблонные классы и их функции обычно определяются в заголовочных файлах, так как компилятору нужно видеть реализацию, чтобы инстанцировать шаблон с конкретным типом.
Пример кода
- В
Stack.h
определен шаблонный классStack
с декларацией всех функций-членов. - В
Stack.tpp
реализованы все функции-члены шаблонного класса. - В
main.cpp
используется шаблонный классStack
для типаint
.
Определение шаблонного класса в заголовочном файле (Stack.h
)
#ifndef STACK_H
#define STACK_H
#include <vector>
#include <stdexcept>
template<typename T>
class Stack {
private:
std::vector<T> elements;
public:
void push(const T& value);
void pop();
T top() const;
bool isEmpty() const;
size_t size() const;
};
#include "Stack.tpp" // Включение файла с реализацией шаблонных функций
#endif // STACK_H
Реализация функций-членов шаблонного класса в отдельном файле (Stack.tpp
)
template<typename T>
void Stack<T>::push(const T& value) {
elements.push_back(value);
}
template<typename T>
void Stack<T>::pop() {
if (!elements.empty()) {
elements.pop_back();
} else {
throw std::out_of_range("Stack<>::pop(): empty stack");
}
}
template<typename T>
T Stack<T>::top() const {
if (!elements.empty()) {
return elements.back();
} else {
throw std::out_of_range("Stack<>::top(): empty stack");
}
}
template<typename T>
bool Stack<T>::isEmpty() const {
return elements.empty();
}
template<typename T>
size_t Stack<T>::size() const {
return elements.size();
}
Использование шаблонного класса в файле (main.cpp
)
#include <iostream>
#include "Stack.h"
int main() {
Stack<int> intStack;
intStack.push(1);
intStack.push(2);
intStack.push(3);
std::cout << "Top element: " << intStack.top() << std::endl; // Вывод: 3
intStack.pop();
std::cout << "Top element after pop: " << intStack.top() << std::endl; // Вывод: 2
std::cout << "Stack size: " << intStack.size() << std::endl; // Вывод: 2
return 0;
}