std :: for_eachの多態的なファンクター
-
03-07-2019 - |
質問
コード全体でテンプレートを増殖させずに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); }
乾杯、
デイブ
解決
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サポートを取得するまで、このコードはコンパイルできません。
他のヒント
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メンバー変数を持つカスタムファンクターを作成したりするのが読みやすくなります。
BOOST_FOREACHを使用しない理由
正しく覚えていれば、ヘッダーのみのライブラリでもあるため、簡単に使用できます。
ファンクターポインターのラッピングをすべて忘れて、代わりに
bind(functor_pointer、mem_fun1(&amp; MyFunctor :: operator());
ファンクターとして?そうすれば、どのような形や形式でもコピーを管理する必要はありません。
@xtoflの答えに基づいて構築します。配列には&quot; this&quot;ではなく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のコードとの唯一の違いは、バインダー2ではなくバインダー1です。バインダ2ndを使用すると、さまざまな「これ」に同じ番号を渡すことができます。ポインター。バインダ1stを使用すると、さまざまな番号を1つの「this」に渡すことができます。ポインター。