4

コード全体でテンプレートを増殖させることなく、stl アルゴリズム for_each を使用しようとしています。std::for_each は MyFunctor クラスを値でインスタンス化したいと考えていますが、抽象化されているためできません。ポインターを渡し、必要に応じて参照解除するファンクター アダプター クラスを作成しました。

私の質問:

STL または Boost には既にそのようなアダプター クラスがありますか? 車輪を再発明する必要はありません。

 struct MyFunctor  {
     virtual ~MyFunctor() {}
     virtual void operator()(int a) = 0; 
 }

 namespace {
     template<typename FunctorType, typename OperandType> struct
 FunctorAdapter
     {
         FunctorAdapter(FunctorType* functor) : mFunctor(functor) {}
         void operator()(OperandType& subject)
         {
             (*mFunctor)(subject);
         }

         FunctorType* mFunctor;
     }; }

 void applyToAll(MyFunctor &f) {
     FunctorHelper<MyFunctor, int> tmp(&f);
     std::for_each(myvector.begin(), myvector.end(), tmp); }

乾杯、

デイブ

4

6 に答える 6

5

の関数アダプター (およびそのシム) を使用できますfunctional

#include <functional>

using namespace std;
for_each( vec.begin(), vec.end(), :mem_fun_ptr( &MyClass::f ) );

コンテナーにオブジェクトへのポインターが含まれている場合は を使用しmem_fun_ptr、それ以外の場合は を使用しますmem_fun。これらの次に、1 つの引数を取るメンバー関数のラッパーがあります:mem_fun1_ptrおよびmem_fun1.

@Evan:実際、各オブジェクトに対して同じ引数でメンバー関数を呼び出すことができます。mem_fun1ラッパーの最初の引数はthisポインターで、2 番目はメンバー関数の引数です。

for_each( vec.begin(), vec.end(), bind2nd( mem_fun_ptr( &MyClass::f ), 1 ) );

より多くの引数を使用すると、自分でループを作成したり、引数を表す const メンバー変数を持つカスタム ファンクターを作成したりすることがより読みやすくなります。

于 2008-10-20T17:11:39.020 に答える
4

ここで tr1::ref が役立つかもしれません --- これは参照ラッパーであるため、標準アルゴリズムへの参照によりバインドまたは関数オブジェクト (抽象オブジェクトであっても) への参照によって通常のオブジェクトを渡すことができます。

// requires TR1 support from your compiler / standard library implementation
#include <functional>

void applyToAll(MyFunctor &f) {
    std::for_each(
        myvector.begin(), 
        myvector.end(), 
        std::tr1::ref(f) 
    ); 
}

ただし、decltype をサポートしないコンパイラは、抽象型への参照の受け渡しを拒否する可能性があることに注意してください。そのため、C++0x のサポートを取得するまで、このコードはコンパイルされない可能性があります

于 2008-10-20T22:52:11.547 に答える
0

@xtoflの答えに基づいて、配列には「this」ポインターではなくintが含まれているため、正しい呪文は

class MyClass
{
  virtual void process(int number) = 0;
};
MyClass *instance = ...;

for_each( vec.begin(), vec.end(), binder1st(instance, mem_fun_ptr(&MyClass::process) );

@xtofl のコードとの唯一の違いは、binder2nd ではなく、binder1st です。binder2nd を使用すると、同じ番号をさまざまな「this」ポインターに渡すことができます。binder1st を使用すると、さまざまな数値を 1 つの "this" ポインターに渡すことができます。

于 2008-10-20T20:59:22.990 に答える
0

ファンクターポインターのラッピングをすべて忘れて、代わりに bind(functor_pointer,mem_fun1(&MyFunctor::operator()); ファンクターとして使用するのはどうですか? そうすれば、形や形を問わずコピーを管理する必要がなくなります。

于 2008-10-20T17:17:11.863 に答える
0

BOOST_FOREACH を使用しないのはなぜですか?

http://www.boost.org/doc/libs/1_35_0/doc/html/foreach.html

于 2008-10-20T17:42:39.300 に答える
0

Boost::Functionの恩恵を受けることができるように聞こえます。

私の記憶が正しければ、これもヘッダーのみのライブラリなので、簡単に使用できます。

于 2008-10-20T17:46:27.030 に答える