...ライブラリから何か他のものが呼び出されない限り。これは最小限の例です。
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();
}
test2.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";
}
2 つを一緒にコンパイルすると、プログラムは期待どおりに動作します。
$ 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) を使用しています。