2011-10-06 14 views
5

現在、テンプレート化された関数でいくつかの演習を行っています。 私は変換アルゴリズムの実装を書いています。 私は次のようにそれをやったし、それが動作します: テンプレートを使用したラムダ

template <class in, class out, class T> 
out stransform(in b, in e, out d, T p(const T&)) { 
    while (b != e) 
     *d++ = p(*b++); 
    return d; 
} 

通常と同じように、私は今

stransform(begin(vec1), end(vec1), back_inserter(vec2), predi<double>); 

のように明示的なタイプと述語を呼び出す必要があります変換、私はCにつまずい++ 11ラムダとこのように私の関数を呼び出すしたい:私は種類を推定するカントというコンパイルエラーを取得しないものと

stransform(begin(vec1), end(vec1), back_inserter(vec2), [] (double x) ->double {return x * 10;}); 

。 これは私のラムダのT型を実際に2回定義しているので理解できません。

私は、それが働いている元の変換関数もチェックしました。私はその後、そのうちのimplementationをチェックし、それは明らかに関数全体のテンプレートクラスで実装されています。 これは、テンプレートで述部を実装する正しい方法ですか?これが機能するには、ポインタ、ラムダや関数オブジェクトを受け入れます

template <class in, class out, class UnaryPredicate> 
out stransform(in b, in e, out d, UnaryPredicate p); 

答えて

13

述語は、通常、単純なテンプレート引数です。

+0

私はトランスフォームの実装を読んだ後、それほど簡単だと思っていました。私はまだ私が他の場合にはうまくいかない理由はまだ不思議です。 – inf

+5

@bamboonラムダは関数ではなく関数オブジェクトであるため、状態を保持することができるので(これはクロージャであり、単なる関数ではありません)、私は推測します。 –

+1

キャプチャを実行しないラムダは、通常の関数(ポインタ)に変換可能であることに注意してください。 – spraff

2

T p(const T&)は、Tを参照番号で受け取る関数の型です。ラムダの引数は、値はです。

stransform (
    begin (vec1), 
    end (vec1), 
    back_inserter (vec2), 
    [] (const double & x) -> double { 
     return x * 10; 
    }); 

これは動作するはずです。キャプチャを実行しないラムダは、通常の関数に変換可能です。

+1

しかし、関数ポインタだけでなくファンクタでも機能するようにファンクタを再定義することができるときに、なぜ関数ポインタへの不必要な変換に頼っているのですか? – jalf

+0

(msvc2011を使って)私にとっては役に立たない。 – inf

+0

@jalfファンクタを再定義する方が良い解決策です。不変のライブラリコードでこの問題が発生した場合、変換が機能します。 – spraff

2

それは明らかに適切な専門用語についてはさておき

わずか全体の機能のためのテンプレートクラスで実装されています。std::transformは機能テンプレート、関数ではなく。さらに重要なことは、スタイルの宣言で

template<class InputIterator, class OutputIterator, class Functor> 
OutputIterator 
transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f); 

テンプレートパラメータInputIteratorOutputIteratorFunctorはクラス型である必要はありません。この例を考えてみましょう:

// function declaration 
int increment(int); 

int array[] = { 0, 1, 2, 3, 4 }; 
transform(std::begin(array), std::end(array), std::begin(array), increment); 

その後InputIteratorOutputIteratorはがクラス型であるいずれも、int*Functorint(*)(int)であることを推測している - はるかに少ないテンプレートクラスが、私は話を戻そう。そして実際に、transformはちょうど同様キーワードtypenameがもう少し明確テンプレートパラメータの性質にある

template<typename InputIterator, typename OutputIterator, typename Functor> OutputIterator transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f); 

を宣言することができます。彼らは、任意の性質の、種類です。

関連する問題