特殊化された明示的にインスタンス化されたテンプレート クラスがあります。
// a.hh
#pragma once
template<int N>
struct A {
int foo();
};
// a.in
#include "a.hh"
template<>
int A<1>::foo() { return 1; } // specialization for N=1
template<>
int A<2>::foo() { return 2; } // specialization for N=2
// a1.cc
#include "a.in"
template struct A<1>; // explicit instantiation for N=1
// a2.cc
#include "a.in"
template struct A<2>; // explicit instantiation for N=2
上記のファイルは、g++ 4.9.2 でスタティック ライブラリにコンパイルされます。
g++ -Wall -c -o a1.o a1.cc
g++ -Wall -c -o a2.o a2.cc
ar rcs libtest.a a1.o a2.o
a1.o には A<1>::foo() が含まれ、a2.o には A<2>::foo() が含まれていると思いますが、その逆ではありません。 .cc ファイル。
ただし、両方のオブジェクト ファイルに両方の関数が含まれていることがわかります。VS2015RC はリンカの警告も表示します。
a1.obj : warning LNK4006: "public: int __thiscall A<1>::foo(void)" already defined in a2.obj; second definition ignored
a1.obj : warning LNK4006: "public: int __thiscall A<2>::foo(void)" already defined in a2.obj; second definition ignored
なんで?
また、N=2 の特殊化をコメント アウトすると、明示的にインスタンス化された N=2 のケースに未解決の関数があるにもかかわらず、g++ を使用してサイレントにコンパイルされます... (VS2015RC は、「明示的なテンプレートのインスタンス化要求に対して適切な定義が提供されていません」と警告します"、 予想通り)。
明確化- 標準 (14.7.3.6) によると:
[..] クラス テンプレートのメンバーが明示的に特殊化されている場合、その特殊化は、そのような使用が発生するすべての翻訳単位で、暗黙的なインスタンス化を引き起こす特殊化の最初の使用の前に宣言されなければなりません[.]
この一節は、インスタンス化するためには特殊化の使用が必要であることを (暗黙のうちに) 述べています。
私の問題は、その翻訳単位でこの仕様が使用されていないにもかかわらず、 A<2>::foo() が a1.o で暗黙的にインスタンス化されることです。