2012-04-04 14 views
0

私は単純な問題がありますが、C++でファンクターを使用したことがないため、解決方法はわかりません。C++:ファンクショナーと標準:: noobの関数

私は(それは単なる一例である)そのような何かをしたい:

class MyClass 
{ 
    void applyFunction(myFunction); /* WRONG SYNTAX */ 
    double *_x; 
    unsigned int *_size; 
}; 

void MyClass::applyFunction(myFunction) /* WRONG SYNTAX */ 
{ 
    for (unsigned int i = 0; i < _size; ++i) 
     myFunction(_x[i], 10.); 
} 

class OtherClass 
{ 
    void myFunction1(double x, double lim); 
    void myFunction2(double x, double lim); 
    std::vector _v; 
}; 

void OtherClass::myFunction1(double x, double lim) 
{ 
    _v.clear(); 
    if (x > lim) 
     _v.push_back(x); 
} 

void OtherClass::myFunction2(double x, double lim) 
{ 
    _v.clear(); 
    if (x < lim) 
     _v.push_back(x); 
} 

int main() 
{ 
    MyClass myClass; 
    OtherClass otherClass; 
    myClass.applyFunction(otherClass.myFunction1); /* WRONG SYNTAX */ 
    std::cout<<otherClass._v.size()<<std::endl; 
    myClass.applyFunction(otherClass.myFunction2); /* WRONG SYNTAX */ 
    std::cout<<otherClass._v.size()<<std::endl; 
     return 0; 
} 

ファンクタ/ STD ::機能を使用するための正しい構文でしょうか?

ありがとうございました!

+0

、あなたは何をする正確に何をしようとしていますか? Wikipediaページには典型的な例が示されています。 – Pubby

+1

コードにエラーが多すぎます。 'std :: vector _v'、' double * _x; 'は' _x [i] 'として使われ、' 'unsigned int * _size;'は 'i <_size'や' x> lim'などとして使われます。 –

答えて

4

私はあなたの言葉で、このためにファンクタを使いたいと思います。ちょうど笑顔のために、私はあなたがこれを "正しい"方法でやりたいと思っています。コンパイルできる構文を見つけ出すだけではなく、おそらく実行しています。

この場合、標準ライブラリには、あなたがやっていることの多く(特にC++ 11)をサポートするアルゴリズムがすでに用意されています。いくつかの基準を満たすデータをターゲットベクターにコピーするには、std::copy_ifが必要です(C++ 98/03にはありませんが、比較の意味を逆にしてstd::remove_copy_ifを使用する必要があります)。あなたがC++ 11利用可能がある場合

template <class T> 
class less_than { 
    T limit; 
public: 
    less_than(T lim) : limit(lim) {} 
    bool operator()(T const &val) { return val < limit; } 
}; 

std::copy_if(source.begin(), 
      source.end(), 
      std::back_inserter(target), 
      less_than<int>(10)); 

は、しかし、それは代わりに、ラムダを使用することがおそらくより便利です::

std::copy_if(source.begin(), 
      source.end(), 
      std::inserter(target), 
      [](int v) { return v < 10;}); 

これを使用して

、あなたのコードは次のようになりラムダは、基本的にコンパイラに匿名ファンクションクラスを生成させる単なる方法ですので、両者の違いはあまりありませんが、ラムダはかなりのタイピングをしています。

あなたがC++ 03で立ち往生している場合は、基本的には、比較を反転:

template <class T> 
class greater_than { 
    T limit; 
public: 
    bool operator()(T const &val) { 
     return val > limit; 
    } 
}; 

std::remove_copy_if(src.begin(), 
        src.end(), 
        std::back_inserter(dst), 
        greater_than(10)); 

また、あなたはかなり簡単に独自のcopy_ifを書くことができ - それはC++ 98の外に残っていました/ 03主に見落としではなく、言語が提供していないものやそれ以外のものが必要なわけではありません(私が思い出したように、すべての境界条件を正確にするのはちょっと難しいかもしれません)。何が価値があるために

、私はまた、標準ライブラリはstd::lessstd::greaterを持っていることに注意しなければならないので、私は上記の与えてくれたless_thangreater_thanファンクタは実際には必要ありません。残念ながら、彼らはあなたがそれらを定数と比較するために取得するstd::bind1stまたはstd::bind2ndを使用する必要があり、我々はここでやっているようにそれらを使用するために、比較を行います。

std::remove_copy_if(src.begin(), 
        src.end(), 
        std::ostream_iterator<int>(std::cout, "\n"), 
        std::bind1st(std::less<int>(), 10)); 
1
void applyFunction(std::function<void(double, double)>); 
// ... 
applyFunction(std::bind(&OtherClass::myFunction1, &otherClass));