模板外部链接不起作用
Templates external linkage does't work
标准说模板名称有 external linkage。
我的问题是:“当我在两个 .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
temp_1.cpp 不生成任何代码,因为模板是为实现编译的,编译器只能为 [=10 找到 class =] 在 temp_2.cpp.
这就是您没有收到任何错误的原因。
它在某种程度上可以与宏进行比较:模板 class 就像 #define
,实现就像在代码中使用宏,在 cpp 的末尾 "macro" 未定义,仅保留其实现。
编辑:
正如我上面写的,模板本身不生成任何类型,这就是它无法链接的原因。类型定义是当您将 teplate 与 typedef 或变量声明一起使用时。
例如:template<class T> class vector
是一个模板class,它不做任何类型定义,也不产生任何代码。
当您使用它时:vector<int> vInt;
或 typedef vector<int> vInt_t
class 将只为 class T=int
编译,如果您再次将它用于其他类型,它将再次编译为也是那种类型。
只有使用过的模板类型可能有链接,这意味着当你再次定义它时它会是相同的类型。类型 vector<int>
可能有外部链接,(意味着可以是来自库或 dll 等的 return)
标准说模板名称有 external linkage。
我的问题是:“当我在两个 .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
temp_1.cpp 不生成任何代码,因为模板是为实现编译的,编译器只能为 [=10 找到 class =] 在 temp_2.cpp.
这就是您没有收到任何错误的原因。
它在某种程度上可以与宏进行比较:模板 class 就像 #define
,实现就像在代码中使用宏,在 cpp 的末尾 "macro" 未定义,仅保留其实现。
编辑:
正如我上面写的,模板本身不生成任何类型,这就是它无法链接的原因。类型定义是当您将 teplate 与 typedef 或变量声明一起使用时。
例如:template<class T> class vector
是一个模板class,它不做任何类型定义,也不产生任何代码。
当您使用它时:vector<int> vInt;
或 typedef vector<int> vInt_t
class 将只为 class T=int
编译,如果您再次将它用于其他类型,它将再次编译为也是那种类型。
只有使用过的模板类型可能有链接,这意味着当你再次定义它时它会是相同的类型。类型 vector<int>
可能有外部链接,(意味着可以是来自库或 dll 等的 return)