2010-12-03 16 views
4

データ型のセットに対してテンプレートを特化する方法について簡単に質問します。例えば、私はこれがintで仕事をしたいタイプのテンプレートの特殊化

template<typename T> 
inline T getRatio(T numer, T denom){ 
    return (numer/denom); 
} 

、長い、ダブル、私はデータ型のこのセットのためにそれを専門にしたいので浮きます。そのため、ユーザーが 'char'型でこの関数を試行すると、コンパイラはエラーをスローします。 これは私に教えてもらえますか?ただtemplateを拒否しlongdoublefloatのための3つの機能を提供し、 おかげ

+0

だから、それは長い、ダブル、フロート、および他のタイプでのみ動作するようにしたいですか? – EboMike

+0

@EboMike。はい.. – blueskin

答えて

3

は、同様に3つだけのデータタイプlongdoublefloatは関連していると追加のジェネリック版の必要は彼らではありません。

+0

+1:過負荷だけを使用してください。 – Puppy

+0

これは、1つではなく3つの機能を維持することを意味します。 3つの機能と機能の単純さでは大丈夫かもしれませんが、将来はいつかメンテナンスプログラマーの一部が変更されることになることを心配しています。 – KeithB

+0

@KeithB - テンプレート以外の関数がテンプレート関数を呼び出すことができますか? –

-1

テンプレートを特定のタイプのパラメータセットでしかインスタンス化できないように指定する方法はありません。ただし、operator /が定義されていないタイプのコンパイルには失敗します。これで十分です。

APIを設計する際には、ユーザーを驚かせることは避けることをお勧めします。分割可能な2つのものの割合を計算できないと言った場合、ほとんどのユーザーは驚きます。

もしあなたが本当にデフォルトの動作をしたくないのであれば、Flinschの答えは良い妥協点です。

+2

"テンプレートを特定のタイプのパラメータセットでしかインスタンス化できないように指定する方法はありません。 < - 単に真実ではありません。 –

2

あなたがこれを行う可能性があります:

// declaration 
template <typename T> inline T getRatio(T numer, T denom); 

// specialization for long  
template <> 
inline long getRatio<long>(long numer, long denom) { return (numer/denom); } 
// specialization for float 
template <> 
inline float getRatio<float>(float numer, float denom) { return (numer, denom); } 
// specialization for double 
template <> 
inline double getRatio<double>(double numer, double denom) { return (numer/denom); } 

getRatioは、長いfloatまたはdouble以外のタイプで呼び出された場合、これはリンカエラーになります。

+1

オーバーロードまたはSFINAEメソッドがこれより優先されます。コンパイラが(overload/sfinaeのように)関数呼び出しと一致しないときは、通常、行の場所など、問題を見つけるために使用できる情報が得られます。リンカエラーでは、たいていの場合、その関数にリンクしようとしているオブジェクトファイルだけが与えられます。 –

+0

...または静的アサーション。 – UncleBens

5

あなたのやりたいことによって異なります。

template < typename T > is_an_ok_type : boost::mpl::false_ {}; 
template < > is_an_ok_type<int> : boost::mpl::true_ {}; 
... etc... 

template < typename T > 
typename boost::enable_if< is_an_ok_type<T>,T >::type 
get_ratio(T t1, T t2) 
{ 
    return t1/t2; 
} 

あなたが合理的に読めるエラーのいくつかの並べ替えをしたい場合:あなたは、コンパイラは、単にあなたがおそらく最善であるFlinschの答えを、使用することができます呼び出し、またはあなたがSFINAEを使用することができる機能のための適切な解像度を見つけることに失敗する場合代わりに静的なアサーションを使用します。 static_assert(C++ 0x)またはBOOST_STATIC_ASSERTです。

+0

このソリューションをさらに単純化して、すべての "etc"タイプを1つのステートメントに入れることができますか? – ProgramCpp

2

getRatio()機能をint, long, double and floatに限定する場合は、この機能も使用できます。 char型の引数を指定して呼び出すと、 "意味のある"コンパイルエラーが生成されます。コンパイルエラーはthis_type_is_not_allowed_in_getRatioです。

//yourheader.h 
template<typename T> 
inline T getRatio(T numer, T denom) 
{ 
    typedef typelist<int, typelist<long, typelist<double, float>>> allowedtypes; 
    compile_time_checker<contains<allowedtypes, T>::result> this_type_is_not_allowed_in_getRatio; 
    return (numer/denom); 
} 

それは、このヘッダーを使用しています。

//metafunctions.h 
template<typename H, typename T> 
struct typelist 
{ 
    typedef H Head; 
    typedef T Tail; 
}; 

template<typename T, typename Tail> 
struct contains 
{ 
    static const bool result = false; 
}; 

template<typename Head, typename Tail, typename T> 
struct contains<typelist<Head, Tail>, T> 
{ 
    static const bool result = false || contains<Tail, T>::result; 
}; 

template<typename T, typename Tail> 
struct contains<typelist<T, Tail>, T> 
{ 
    static const bool result = true || contains<Tail, T>::result; 
}; 

template<bool b> struct compile_time_checker; 
template<> struct compile_time_checker<true> {}; 

希望、それはあなたを助けます。 すべてのコードをただ1つの関数で書くことができます!

関連する問題