...除非调用库中的其他内容。这是一个最小的例子。
test1.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中)。
答案 0 :(得分:2)
使用MSVC2010SP1我的结果略有不同:
一起编译,因为我没有得到“C bar”。这是预期的,因为test1.cpp和test2.cpp是单独的编译单元,并且没有专门化的前向声明,另一个包含test1.cpp将实例化其默认的“普通条”,而test2.cpp将不会实例化“C”吧“因为它看不到任何使用它。
当我取消注释proofOfTwoLinked();我得到“Yup,two is linked”,这是因为“proofOfTwoLinked()”是向前声明的。我仍然没有得到“C bar”这是预期的,因为它没有在test1.cpp
中向前声明当我再次编译时添加
template <> void Foo<C>::bar();
to test1.cpp我收到链接器错误,因为虽然test1.cpp编译单元现在知道有一个
template <> void Foo<C>::bar()
在某处,test2.cpp仍然不知道有人在使用它。
当我再次编译时添加
template void Foo<C>::bar();
到test2.cpp一切正常,我得到“C吧”。注意
template void Foo<C>::bar();
必须在其定义之前。
据我所知,MSVC表现正常,gcc在你的情况下表现得很奇怪。我使用http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf第14.7节作为参考,它可能会有所帮助。