1つのメソッドを持つヘッダーで宣言するテンプレートクラスがあり、ヘッダーにそのメソッドの定義はありません。.ccファイルでは、ヘッダーで宣言せずに、そのメソッドの特殊化を定義します。別の.ccファイルで、特殊化が存在するさまざまなテンプレートパラメーターのメソッドを呼び出します。次のようになります。
foo.h:
template<typename T>
class Foo {
public:
static int bar();
};
foo.cc:
#include "foo.h"
template<>
int Foo<int>::bar() {
return 1;
}
template<>
int Foo<double>::bar() {
return 2;
}
main.cc:
#include <iostream>
#include "foo.h"
int main(int argc, char **argv) {
std::cout << Foo<int>::bar() << std::endl;
std::cout << Foo<double>::bar() << std::endl;
return 0;
}
このプログラムは、すべてのC ++標準(c ++ 98、gnu ++ 98、c ++ 11、およびgnu ++ 11)のgcc 4.7.2で正常にコンパイルされ、リンクされます。出力は次のとおりです。
1
2
これは私には理にかなっています。main.cc変換ユニットは、その定義bar()
または特殊化を認識しないため、他の変換ユニットbar()
での特殊化されていない定義の明示的なインスタンス化を使用する呼び出しを想定していますbar()
。ただし、名前マングリングは予測可能であるため、foo.ccの特殊化は、特殊化されていない定義の明示的なインスタンス化と同じシンボル名を持ちます。したがって、main.ccは、その変換単位で宣言されることなく、これらの特殊化を使用できます。
私の質問はこれです:これは事故ですか、それともこの動作はC ++標準で義務付けられていますか?言い換えれば、このコードは移植可能ですか?
私が見つけた最も関連性のある以前の質問は、テンプレートクラスメンバーの特殊化の宣言ですが、この特定のケースについては説明していません。
(これがなぜ私にとって重要なのか疑問に思われるかもしれませんが、これは、このようなコードを一種のコンパイル時ルックアップテーブルとして使用しているためです。特殊化を宣言しないと、はるかに短くなります。)