Внешние ссылки на шаблоны не работают - PullRequest
0 голосов
/ 10 мая 2018

Стандарт говорит, что имена шаблонов имеют внешнюю связь .

Мой вопрос: " Почему нет ошибки компоновщика, когда я объявляю одни и те же шаблоны в двух файлах .cpp и компилирую эти файлы вместе? "

Глобальные имена функций имеют внешнюю связь, как имена шаблонов. Вот почему я предлагаю, чтобы у них было похожее поведение. Но что касается функций, то в этом нет ничего странного, и компоновщик выдает ошибку, а вот для шаблонов почему-то ошибки нет.

temp_1.cpp

#include <iostream>

// error because of external linkage
// void eq_f(){}


template<class T>
void my_func() {
    std::cout << "1!";
}

temp_2.cpp

#include <iostream>

// external linkage
// void eq_f(){}

template<class T>
void my_func() {
    std::cout << "2!";
}

int main() {
    my_func<int>();
    return 0;
}

Команда:

clang++ temp_1.cpp temp_2.cpp -std=c++17

1 Ответ

0 голосов
/ 10 мая 2018

temp_1.cpp не производит никакого кода, потому что шаблон скомпилирован для реализаций, единственный класс, который компилятор может найти для main, находится в temp_2.cpp .

Вот почему вы не получаете никакой ошибки.

Это как-то можно сравнить с макросом: класс шаблона похож на #define, реализации похожи на использование макроса в коде, в конце cpp «макрос» не определен, только реализации из этого осталось.

EDIT:

Как я писал выше, сам шаблон не генерирует никаких типов, поэтому его нельзя связать. определение типа это когда вы используете teplate с typedef или объявлением переменной.

например: template<class T> class vector является классом шаблона, он не дает определения типа и не производит никакого кода.

Когда вы используете его: vector<int> vInt; или typedef vector<int> vInt_t класс будет скомпилирован только для class T=int, если вы используете его снова для другого типа, он будет скомпилирован снова и для этого типа.

только используемый шаблонный тип может иметь связь, это означает, что при повторном его определении он будет того же типа. тип vector<int> может иметь внешнюю связь (средства могут быть возвращены из библиотеки или dll и т. д.)

...