Comments 9
Не получится объявить шаблонные функции в .h, а определения давать в .cpp. Такой код просто откажется компилироваться.
Вобще если сильно хочется то можно.
// h
template<class T> void fn(T t) { void _fn(T t); _fn(t); }
// cpp
void _fn(int) {}
void _fn(double) {}
ps: кстати все <> скобки в примерах были конфискованы, сделав код слегка криповым.
Есть для этого встроенная функциональность, explicit instantiation:
// header
// declaration of template
template<typename T> void fn(T t);
// declaration of instantiation
extern template void fn<int>(int);
// implementation
// definition of template
template<typename T> void fn(T t) {
// body
}
// definition of instantiation
template void fn<int>(int);
Само собой в этом случае шаблон можно использовать только с теми типами которые были явно перечислены.
Precompiled headers? Unity build?
Тема оптимизации C++ шаблонов не раскрыта. Необходимо было рассказать, как в библиотеках типа STL, Boost, ... с этим борются, а там есть несколько способов.
Как реализованы разные hash-map. Статическая таблица вызовов функций, инициализируется для каждого типа.
struct RawTableOps {
size_t (*hash)(const void* key);
...
class RawTable {
private:
const RawTableOps* ops_;
...
template<class K, class V,
class H = std::hash<K>,
class E = std::equal_to<K>>
class HashMap : private RawTable {
public:
HashMap() : RawTable(&ops) {}
...
Как реализованы разные вектора. Все тяжёлые алгоритмы работают в базовом классе, приходится гонять через void* и size_t всё, и шаблонная обёртка преобразует к нужному типу.
class _Vec_common {
protected:
...
template<class T, class Alloc = std::allocator<T>>
class tiny_vector : private _Vec_common {
...
private:
T* data_{}; size_t size_{}, cap_{};
нет не для каждого она обьявлена как воид чтобы в момент создания по К создать E чтобы иметь ==, тоесть как только указан К, а он будет указан, будет происходить сравнение значения по К, а воид чтобы работать с типами, у вектора с воид таже петрушка и вся эта история тянется шлейфом из С, это сделано для того чтобы пользователь никуда больше не писал свой кастомный тип а контейнер работал только от указания типа своего
тоесть стл пускай такой будет можно написать я так сделал using v=v<int>;
и в качестве кастомного типа использую те которые от юзинга получились
а так пришлось бы добавлять 2 разных типа с одинаковой логикой и внутренностями с разным типом
спасибо интересно, прочитал на одном дыхании
хочу чтобы на С++ был слой С всё таки ) врубил флаг и не надо никакие доказательства какой там класс, чтоб был лейаут прям рабочий от С)
чтобы прям его - тоесть С можно было прям заколбасить в include и пользоваться им нативно
Я не совсем понял, как именно импортирующий файл поймёт, что надо использовать явные инстанции, если они не добавлены в export и "не помещаются в пространство имён" этого файла. Разве из этого не следует, что компилятору придётся выполнить неявную инстанциацию?
Оптимизируем C++ шаблоны: от инлайнинга до модулей