Pull to refresh

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);

Само собой в этом случае шаблон можно использовать только с теми типами которые были явно перечислены.

Только definition of instantiation звучит странно, это просто момент, когда компилятор задумывается "пойду-ка инстанцировать шаблон с такими-то параметрами".

Тема оптимизации C++ шаблонов не раскрыта. Необходимо было рассказать, как в библиотеках типа STL, Boost, ... с этим борются, а там есть несколько способов.

  1. Как реализованы разные 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) {}
...
  1. Как реализованы разные вектора. Все тяжёлые алгоритмы работают в базовом классе, приходится гонять через 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 и "не помещаются в пространство имён" этого файла. Разве из этого не следует, что компилятору придётся выполнить неявную инстанциацию?

Sign up to leave a comment.

Articles