以下构建设置在使用GCC(4.6.3)的Linux上运行良好,但在使用GCC(4.7.2)的MinGW上运行良好.
$cat Makefile
all:
g++ -c foo.cpp
g++ -c bar.cpp
g++ bar.o foo.o -o bar
$cat foo.h
#ifndef FOO_H
#define FOO_H
#include <iostream>
template <typename T>
void foo(T x) {
std::cout << "Hello World!" << std::endl;
}
#endif
$cat foo.cpp
#include "foo.h"
template <>
void foo(int x) {
std::cout << "Hello Int!" << std::endl;
}
$cat bar.cpp
#include "foo.h"
int main() {
foo <int> (1);
}
在Linux上,我们具有:
$make
g++ -c foo.cpp
g++ -c bar.cpp
g++ bar.o foo.o -o bar
$./bar
Hello Int!
这是我所期望的.在Windows上,
$make
g++ -c foo.cpp
g++ -c bar.cpp
g++ bar.o foo.o -o bar
foo.o:foo.cpp:(.text+0x0): multiple definition of `void foo<int>(int)'
bar.o:bar.cpp:(.text$_Z3fooIiEvT_[__Z3fooIiEvT_]+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
make: *** [all] Error 1
我怀疑这与弱符号有关.意思是,在Linux上,我们在foo.o中
00000000 T _Z3fooIiEvT_
并在bar.o中
00000000 W _Z3fooIiEvT_
在Windows上我们在foo.o中有
00000000 T __Z3fooIiEvT_
并在bar.o中
00000000 T __Z3fooIiEvT_
因此,没有弱符号可以覆盖.
解决此问题的最佳方法是什么?在实际情况下,我有一个带有许多模板定义的标头foo.h.我专门研究了其中一些,并将这些定义放在foo.cpp中,该文件随后被编译到库中.然后,我将标题和库提供给用户.如果可能的话,我总是想在foo库中使用特殊化.如果专业化不存在,我想在foo标头中使用模板定义.
编辑
foo.h的以下修改似乎可以解决问题
$cat foo.h
#ifndef FOO_H
#define FOO_H
#include <iostream>
template <typename T>
void foo(T x) {
std::cout << "Hello World!" << std::endl;
}
template <>
void foo(int x);
#endif
基本上,foo的int版本的原型必须位于标头中.这与BoBTFish的注释一致,该注释要求该标准要求“必须在首次使用之前声明专业化”.无论如何,这是设置专业化库的最佳方法吗?
解决方法:
不知道编译器的复杂性,但是无论如何您都违反了The Standard:
14.7.3 Explicit specialization:
6 If a template, a member template or a member of a class template is
explicitly specialized then that specialization shall be declared
before the first use of that specialization that would cause an
implicit instantiation to take place, in every translation unit in
which such a use occurs; no diagnostic is required.
因此您的程序格式不正确.