あなたは正しい軌道に乗っていると思います。
秘訣は次のとおりです。どの翻訳単位でも、専門化の前にテンプレートをインスタンス化しないでください。
例えば:
// test.h
#ifndef TEST_H
#define TEST_H
template <typename T>
extern int variable;
template <> extern int variable<char>;
template <> extern int variable<int>;
#endif // TEST_H
それで:
// test2.cpp
#include "test.h"
template <> int variable<char> = 23;
template <> int variable<int> = 24;
そして最後に:
// test.cpp
#include "test.h"
#include <iostream>
int
main()
{
std::cout << variable<char> << '\n';
std::cout << variable<int> << '\n';
}
私にとって、これは次の出力を出力します:
23
24
アップデート
TC は以下のコメントで、特殊化は最初に使用する前に宣言する必要があると指摘しているので、上記の「test.h」を更新してそれを行いました。
更新 2
若干の実装の相違があるようです。clang はこの問題を処理しているようです:
template <typename T>
extern int variable;
template <> extern int variable<char>;
template <> extern int variable<int>;
#include <iostream>
int
main()
{
std::cout << variable<char> << '\n';
std::cout << variable<int> << '\n';
}
template <> int variable<char> = 23;
template <> int variable<int> = 24;
http://melpon.org/wandbox/permlink/DGYKvvoPbmRIHaFi
ただし、gcc でエラーが発生します。
prog.cc:4:13: error: explicit template specialization cannot have a storage class
template <> extern int variable<char>;
^~~~~~
prog.cc:5:13: error: explicit template specialization cannot have a storage class
template <> extern int variable<int>;
^~~~~~
標準と Core Issues リストを検索しましたが、どちらのコンパイラが正しいかを示すものは見つかりません。誰かがそのような証拠を見た場合は、この回答に喜んで含めます。