std::for_each の std::map 要素にアクセスするための Boost.Bind
質問
キーを持つ単純な構造体を保存するマップがあります。構造体には 2 つのメンバー関数があり、1 つは const で、もう 1 つは const ではありません。std::for_each を使用して const 関数を呼び出すことは問題なくできましたが、非 const 関数を呼び出す場合にはいくつかの問題が発生します。
struct MyStruct {
void someConstFunction() const;
void someFunction();
};
typedef std::map<int, MyStruct> MyMap;
MyMap theMap;
//call the const member function
std::for_each(theMap.begin(), theMap.end(),
boost::bind(&MyStruct::someConstFunction, boost::bind(&MyMap::value_type::second, _1)));
//call the non-const member function
std::for_each(theMap.begin(), theMap.end(),
boost::bind(&MyStruct::someFunction, boost::bind(&MyMap::value_type::second, _1)));
const メンバー関数の呼び出しは正常に機能しますが、boost は内部的にどこかに const MyStruct を期待しているようで、そのため MSVC7.1 では次のコンパイル エラーが発生して失敗します。
ブースト\バインド\mem_fn_template.hpp(151):エラー C2440:'口論' :'const MyStruct *__w64 ' から 'MyStruct *const ' に変換できません
テンプレートパラメータを正しく設定する方法についてアドバイスをいただければ幸いです。バインドがパラメータを正しく認識し、非 const 関数を呼び出せるようにします。
ありがとう、カール
解決
IIRC、Boost.Bindは、そのメンバーの能力を結合するためのboost::mem_fn
を使用しています。さて、あなたは mem_fun の(スクロールダウンを見れば// data member support
部分)に、あなたはまだある間、それは、constのようにそののresult_typeをtypedefで&ことがわかります非const引数から非constメンバの抽出をサポートしている関数呼び出し演算子のオーバーロードがあります。
このような問題は、これがBoost.Bindの戻り値の型推論メカニズムを混乱させるということであるようです。ソリューションは、このように明示的に結果がconstのではないことをバインドを言うだろう:
//call the non-const member function
std::for_each(theMap.begin(), theMap.end(),
boost::bind(&MyStruct::someFunction,
boost::bind<MyStruct&>(&MyMap::value_type::second, _1)
)
);
他のヒント
あなた自身が、私はあなたがBoost.RangeExライブラリを使用することをお勧めこの多くを行うために持つ見つけた場合:
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/mem_fn.hpp>
#include <map>
struct MyStruct {
void someConstFunction() const;
void someFunction();
};
typedef std::map<int, MyStruct> MyMap;
MyMap theMap;
int main()
{
//call the const member function
boost::for_each(theMap | boost::adaptors::map_values,
boost::mem_fn(&MyStruct::someConstFunction));
//call the non-const member function
boost::for_each(theMap | boost::adaptors::map_values,
boost::mem_fn(&MyStruct::someFunction));
}
これは、ブーストに受け入れられていますが、それはまだ公式のディストリビューションに付属していません。それはあなたがからそれををダウンロードすることができなくなるまでボールトする(zipファイルへのダウンロードリンク)をブースト。
すでに依存している場合 Boost
, 、チェックしてみてもいいかもしれません ブーストフォーリーチ
BOOST_FOREACH(MyMap::value_type const& val, MyMap)
{
val.second.someConstFunction();
}
非常に読みやすいですが、パフォーマンスの問題についてはわかりません。
また、マクロ内で型指定されたテンプレートを「エスケープ」しないと使用できないことにも注意してください。 ,
キャラクター:
- 前の typedef によって
- または、型を 2 番目の括弧で囲んで使用します。
一つの問題私が発見:2番目のバインドは、非メンバ関数のために呼ばれています。第二のデータメンバではなく、スタンダードの方法::対である