2011-05-31 9 views
1

私はこのテンプレート機能があります。指定する型

template <class P> 
double Determinant(const P & a, const P & b, const P & c) { 
    return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y); 
} 

が、私はdoubleにすべての時間を戻り値の型を強制的に避けたい - P :: xとP :: yはintでもかまいません。両方の状況でこの関数が必要です。このようなxとyのタイプを指定する方法はありますか?

//doesn't compile; can't deduce template argument for T 
template <typename T, class P> 
T Determinant(const P & a, const P & b, const P & c) { 
    return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y); 
} 

編集:言及するのを忘れて申し訳ありません:私のコンパイラがVC2005

EDIT2です残念ながら、私はPのための構造体の実装を変更することはできません。私が扱うポイントタイプの1つは、{ long x; long y; }としてハードコードされているMFC/ATLのCPointです。

+0

あなたはどのコンパイラを使用していますか? – Xeo

+0

vc2005 - 今質問に編集されました。 –

答えて

7

コンパイラは、関数の引数から関数テンプレートの戻り型を推定できません。型控除は関数の引数のみで行われます。

C++ 03では、としてあなたのクラスでのtypedef を定義することができます。

struct A //suppose A is going to be type argument to your function template 
{ 
    int x, y;  //I'm assuming type of x and y is same! 
    typedef int value_type; //type of x and y! 
}; 

そして、あなたはあなたの関数を再書き込みしてきたように:

template <class P> 
typename P::value_type Determinant(const P & a, const P & b, const P & c) { 
    return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y); 
} 

お知らせreturn-type now、その依存型。その:

typename P::value_type 

ここではキーワードtypenameが必要です。


申し訳ありませんが、構造体を変更できないと言っているように、代わりに特性を使用できます。ここでこれを行う方法を次のとおりです。

template<typename T> struct PTraits; 

//Suppose this is your type which you can't modify 
struct A //A is going to be type argument to your function template 
{ 
    long x, y; 
}; 

//specialization: defining traits for struct A 
template<> 
struct PTraits<A> 
{ 
    typedef long value_type; //since type of A::x and A::y is long! 
}; 

そして、あなたの関数テンプレートは次のようになります。

template <class P> 
typename PTraits<P>::value_type Determinant(const P & a, const P & b, const P & c) { 
    return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y); 
} 

お知らせリターン型。そのわずかに異なる今:

typename PTraits<P>::value_type 

ここでも、value_typeは依存名なので、キーワードtypenameが必要です。

私がしたように、関数テンプレートに渡すタイプごとにPTraits<>を特化しなければならないことに注意してください。

+1

きちんとしたトリックNawaz;以前はそれを考えなかった。残念ながら、私は構造体の実装を変更することはできません。私が扱うポイントタイプの1つはMFC/ATLのCPointです。これは '{long x;}でハードコードされています。長いy; } '、この種の有用なtypedefはありません。 –

+0

@martin_ljchan:2番目の解決策を見てください! – Nawaz

+1

特色! :)私はそのことについて何度か読まなければならない。 –

2

あなたは、Visual Studio 2010またはGCC 4.5+を使用している場合は、末尾の戻り値の型のフォームを使用することができますが:decltype

template<class P> 
auto fun(const P& a) -> decltype(a.x + a.y){ 
    return a.x + a.y; 
} 

おかげで私たちは、自動的に右の戻り値の型を取得します。また、計算は本体で一度だけ実行され、後続の戻りでは実行されません。

+0

タグにC++ 0xはありません –

3

私はこれに特色スタイルのアプローチを使用したい:

template<typename T> struct DeterminantReturnInfo {}; 
template<> struct DeterminantReturnInfo<MyType> { typedef MyOtherType ReturnType; } 

template< typename T > 
typename DeterminantReturnInfo<T>::ReturnType Determinant(const P & a, const P & B, const P & c) 
{ 
    return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y); 
} 

あなたはそれが倍増し、デフォルトにしたい場合は、あなただけの初期テンプレートにtypedef double ReturnType;を追加します。

+0

'typedef ReturnType double;'?間違った構文 – Nawaz

+0

確かに。一定。 (編集ボタンで訂正してしまったのは間違いなのですが) –

0

戻り値を確認するメンバー変数x/yの型を入力します。あなたはタイプTを返さないかもしれません。

関連する問題