Есть несколько подходов, но ни один из них не идеален.
Во-первых, «традиционный» подход заключается в определении функтора, который делает то, что вам нужно:
struct SetCollideModeFunc {
SetCollideModeFunc(const std::string& m) : m(m) {}
void operator()(std::pair<std::string, Body*>& p) {
Body* b = p.second;
b->SetCollideMode(m);
}
const std::string& m;
};
void Model::SetCollideMode( const std::string &m )
{
std::for_each(bodies.begin(), bodies.end(), SetCollideModeFunc(m));
}
Это не экономит много кода, но позволяет отделить итерацию от операции, которую вы хотите применить. И если вам нужно установить коллизидный режим несколько раз, вы, конечно, можете повторно использовать функтор.
Более короткая версия возможна с библиотекой Boost.Lambda, которая позволит вам определить встроенный функтор. Я не могу вспомнить точный синтаксис, так как я не часто использую Boost.Lambda, но это будет примерно так:
std::for_each(bodies.begin(), bodies.end(), _1.second->SetCollideMode(m));
В C ++ 0x вы получаете языковую поддержку лямбда-выражений, позволяющую использовать синтаксис, подобный этому, без использования сторонних библиотек.
Наконец, Boost.ForEach может быть опцией, допускающей такой синтаксис:
void Model::SetCollideMode(const std::string &m)
{
BOOST_FOREACH ((std::pair<std::string, Body*> p), bodies) // note the extra parentheses. BOOST_FOREACH is a macro, which means the compiler would choke on the comma in the pair if we do not wrap it in an extra ()
{
p.second->SetCollideMode(m);
}
}