...除非调用库中的其他内容。这是一个最小的例子。
测试1.cpp
#include <iostream>
void proofOfTwoLinked();
template <class T>
struct Foo
{
void bar(){ std::cout << "normal bar\n"; }
};
struct A{};
struct B{};
struct C{};
struct D{};
template <> void Foo<B>::bar(){ std::cout << "B bar\n"; }
int main()
{
Foo<A> a;
Foo<B> b;
Foo<C> c;
Foo<D> d;
a.bar();
b.bar();
c.bar();
d.bar();
//proofOfTwoLinked();
}
测试2.cpp
#include <iostream>
struct C;
template <class T>
struct Foo
{
void bar(){ std::cout << "normal bar\n"; }
};
template <> void Foo<C>::bar(){ std::cout << "C bar\n"; }
void proofOfTwoLinked()
{
std::cout << "Yup, two is linked\n";
}
如果我将两者一起编译,程序将按预期工作:
$ rm test; rm *.a; rm *.o; g++ -c test1.cpp; g++ -c test2.cpp; g++ -o test test1.o test2.o; ./test
normal bar
B bar
C bar
normal bar
如果我编译 test2,将其放入存档中,然后将程序链接到该文件...当调用 c.bar() 时,不会执行类型 C 的特化:
$ rm test; rm *.a; rm *.o; g++ -c test1.cpp; g++ -c test2.cpp; ar -r test2.a test2.o; g++ -o test test1.o test2.a; ./test
ar: creating test2.a
normal bar
B bar
normal bar
normal bar
但是如果我取消注释 test1 (proofOfTwoLinked) 的最后一个函数调用,然后再次编译,则执行特化。
$ rm test; rm *.a; rm *.o; g++ -c test1.cpp; g++ -c test2.cpp; ar -r test2.a test2.o; g++ -o test test1.o test2.a; ./test
ar: creating test2.a
normal bar
B bar
C bar
normal bar
Yup, two is linked
这让我觉得很奇怪,而且肯定出乎我的意料。这实际上是正常行为吗?也许因为在链接器搜索 test2.a 之前,在 main() 中调用的每个函数的某种形式已经存在,它会跳过存档。有没有办法强制链接器“查看整个档案”?
我正在使用 gcc 4.6.1 和 ar 2.21.53(在 ubuntu 中)。