質問の内容。さらに、これをインラインで行うことは可能ですか?
これはアイデアを与えるための小さな例です...
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void do( const Foo<T> &f ) {
z = f.z;
}
// specialize 'do' for Foo<int>, possible inline?
private:
T z;
};
質問の内容。さらに、これをインラインで行うことは可能ですか?
これはアイデアを与えるための小さな例です...
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void do( const Foo<T> &f ) {
z = f.z;
}
// specialize 'do' for Foo<int>, possible inline?
private:
T z;
};
複雑なことをする必要はありません。オーバーロードと委任を使用するだけです。int
オーバーロードを追加するだけでは不十分であることに注意してください。オーバーロードも無効であるT
ことが判明した場合int
、これは無効なオーバーロードになります(同じシグネチャを持つ2つの関数)
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void doIt(const Foo<T> &f ) {
doItImpl(f);
}
private:
template<typename U>
void doItImpl(const Foo<U> &f) {
z = f.z;
}
void doItImpl(const Foo<int> &f) {
/* ... */
}
private:
T z;
};
または、この場合、専門化によってこれを行うことができます
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void doIt(const Foo<T> &f ) {
z = f.z;
}
private:
T z;
};
template<>
inline void Foo<int>::doIt(const Foo<int> &f) {
/* ... */
}
この方法で特殊化を使用できるのは、すべてのテンプレート引数が固定されている場合のみです。つまり、メンバー関数を部分的に特殊化することはできません。
メンバー関数をメンバー関数テンプレートにし、SFINAEを使用することで、この動作を得ることができます(置換の失敗はエラーではありません)。例えば:
template <typename U>
typename std::enable_if<!std::is_integral<U>::value &&
std::is_same<T, U>::value, void>::type
f(const Foo<U>& x)
{
}
template <typename U>
typename std::enable_if<std::is_integral<U>::value &&
std::is_same<T, U>::value, void>::type
f(const Foo<U>& x)
{
}
is_integral
型特性U
は、が整数型であるかどうかをテストします。そうでない場合は、最初のものがインスタンス化されます。そうである場合、2番目がインスタンス化されます。
is_same
タイプ特性は、とが同じタイプであることを確認するためにテストしT
ますU
。これは、メンバー関数テンプレートが。以外のタイプに対してインスタンス化されないようにするために使用されますFoo<T>
。
この例では、C++0x<type_traits>
ライブラリを使用しています。Boostには、使用できるタイプ特性ライブラリもあります。これはほとんど同じように機能します。
あなたはこのようなことをしようとするかもしれません(テストしなかった、うまくいかないかもしれません):
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
template<typename Ty = T>
void do( const Foo<T> &f ) {
z = f.z;
}
template<>
void do<int>( const Foo<T> &f ) {
//specialized code
}
private:
T z;
};