template<typename T>
class CConstraint
{
public:
CConstraint()
{
}
virtual ~CConstraint()
{
}
template <typename TL>
void Verify(int position, int constraints[])
{
}
template <>
void Verify<int>(int, int[])
{
}
};
これをg ++でコンパイルすると、次のエラーが発生します。
名前空間以外のスコープ 'class CConstraint'での明示的な特殊化
VCでは、問題なくコンパイルされます。誰でも回避策を教えてもらえますか?
この場合、VC++は非準拠です。明示的な特殊化は、名前空間のスコープ内になければなりません。 C++ 03、§14.7.3/ 2:
明示的な特殊化は、テンプレートがメンバーである名前空間で宣言されるか、メンバーテンプレートの場合、包含クラスまたは包含クラステンプレートがメンバーである名前空間で宣言されます。
メンバー関数、メンバークラス、またはクラステンプレートの静的データメンバーの明示的な特殊化は、クラステンプレートがメンバーである名前空間で宣言されます。
さらに、C++ 03、§14.7.3/により、含まれるクラスを明示的に特化せずにメンバー関数を特化できないという問題があるため、1つの解決策はVerify()
特殊化された、おそらく無料の関数に転送します。
namespace detail {
template <typename TL> void Verify (int, int[]) {}
template <> void Verify<int>(int, int[]) {}
}
template<typename T> class CConstraint {
// ...
template <typename TL> void Verify(int position, int constraints[]) {
detail::Verify<TL>(position, constraints);
}
};
それを解決する別の方法は、プライベート関数に委任し、その関数をオーバーロードすることです。この方法では、*this
のメンバーデータと外部テンプレートパラメータータイプに引き続きアクセスできます。
template<typename T>
struct identity { typedef T type; };
template<typename T>
class CConstraint
{
public:
template <typename TL>
void Verify(int position, int constraints[])
{
Verify(position, constraints, identity<TL>());
}
private:
template<typename TL>
void Verify(int, int[], identity<TL>)
{
}
void Verify(int, int[], identity<int>)
{
}
};
クラス宣言の外でテンプレートの特殊化を行ってください。 gccはインラインテンプレートの特殊化を許可しません。
別のオプションとして、行テンプレート<>を削除するだけでうまくいくようです。
さらに良いことには、部分的な特殊化とデフォルトのテンプレート引数を組み合わせることができます。このようにVC++コードを変更することはわずかです。これは、特殊な関数の呼び出しを変更する必要がないためです。
template <typename TL, class Dummy=int>
void Verify(int position, int constraints[])
{
}
template <class Dummy=int>
void Verify<int, Dummy>(int, int[])
{
}
メンバーテンプレートを明示的に特殊化できない場合がありますが、部分的に特殊化できます。 2番目のパラメーター「int dummyParam」を追加し、それを特殊化に追加する場合、両方のコンパイラーで機能するはずです。
私はこれを10秒以上前に知っていたわけではありませんが、同じエラーでグーグルで このリンク に遭遇し、メンバーテンプレートの専門化に役立ちました。