当使用不同的对象时,模板专门化的多重定义

当我在不同的目标文件中使用专门的模板时,链接时会出现“多重定义”错误。 我发现唯一的解决scheme涉及使用“内联”function,但它似乎是一些解决方法。 我如何解决这个问题,而不使用“内联”关键字? 如果这是不可能的,为什么?

以下是示例代码:

paulo@aeris:~/teste/cpp/redef$ cat hello.h #ifndef TEMPLATE_H #define TEMPLATE_H #include <iostream> template <class T> class Hello { public: void print_hello(T var); }; template <class T> void Hello<T>::print_hello(T var) { std::cout << "Hello generic function " << var << "\n"; } template <> //inline void Hello<int>::print_hello(int var) { std::cout << "Hello specialized function " << var << "\n"; } #endif 

 paulo@aeris:~/teste/cpp/redef$ cat other.h #include <iostream> void other_func(); 

 paulo@aeris:~/teste/cpp/redef$ cat other.c #include "other.h" #include "hello.h" void other_func() { Hello<char> hc; Hello<int> hi; hc.print_hello('a'); hi.print_hello(1); } 

 paulo@aeris:~/teste/cpp/redef$ cat main.c #include "hello.h" #include "other.h" int main() { Hello<char> hc; Hello<int> hi; hc.print_hello('a'); hi.print_hello(1); other_func(); return 0; } 

 paulo@aeris:~/teste/cpp/redef$ cat Makefile all: g++ -c other.c -o other.o -Wall -Wextra g++ main.c other.o -o main -Wall -Wextra 

最后:

 paulo@aeris:~/teste/cpp/redef$ make g++ -c other.c -o other.o -Wall -Wextra g++ main.c other.o -o main -Wall -Wextra other.o: In function `Hello<int>::print_hello(int)': other.c:(.text+0x0): multiple definition of `Hello<int>::print_hello(int)' /tmp/cc0dZS9l.o:main.c:(.text+0x0): first defined here collect2: ld returned 1 exit status make: ** [all] Erro 1 

如果我取消注释hello.h中的“inline”,代码将会编译并运行,但是这对我来说似乎是一种“解决方法”:如果专用函数很大并且被多次使用,该怎么办? 我会得到一个大的二进制文件? 有没有其他方法可以做到这一点? 如果是的话,怎么样? 如果没有,为什么?

我试图寻找答案,但我所得到的是“使用内联”没有任何进一步的解释。

谢谢

直观地说,当你完全专门化一些东西的时候,它不再依赖于一个模板参数 – 所以除非你使内联专业化,否则你需要把它放在一个.cpp文件而不是.h文件中,否则你最终会违反大卫说,一个定义规则。 请注意,当您部分专门化模板时,部分专业化依然依赖于一个或多个模板参数,因此它们仍然位于.h文件中。

关键字inline更多的是告诉编译器该符号将存在于多个目标文件中,而不违反One Definition Rule而不是实际的内联,编译器可以决定做或不做。

您所看到的问题是,如果没有内联,函数将被编译到包含标头的所有翻译单元中,从而违反了ODR。 添加inline有正确的路要走。 否则,您可以转发宣言专业化,并提供在一个单一的翻译单位,就像你会做任何其他function。

你已经在头文件中明确地实例化了一个模板( void Hello<T>::print_hello(T var) )。 这将创build多个定义。 你可以用两种方法解决它:

1)让你的实例化内联。

2)在头文件中声明实例,然后在cpp中实现它。