bind를 이용하여 map의 element에 for_each 적용하기

Posted at 2008. 9. 14. 23:56 // in S/W개발/C++ 이야기 // by 김윤수


#include <iostream>
#include <map>
#include <boost/mem_fn.hpp>
#include <boost/bind.hpp>

using namespace std;

class Elem {
public:
  Elem() : m_name(), m_val() {}

  Elem(const string& name, int val) : m_name(name), m_val(val) {}

  const string& GetName() const
  {
      return m_name;
  }

  int GetValue() const
  {
      return m_val;
  }

  void SetValue(int val)
  {
      m_val = val;
  }

private:

  string m_name;
  int m_val;

};

struct Print {
  typedef void result_type;

  void operator()(const Elem& e) {
      cout << e.GetName() << "'s value ==> " << e.GetValue() << endl;
  }
};

int
main (int argc, char * const argv[])
{

  map<string, Elem> m;

  m["1"] = Elem("1", 1);
  m["2"] = Elem("2", 2);
  m["3"] = Elem("3", 3);
  m["4"] = Elem("4", 4);
  m["5"] = Elem("5", 5);

  for_each(
    m.begin(), m.end(),
    boost::bind(Print(),
      boost::bind(&map<string, Elem>::value_type::second, _1))
  );

  return 0;
}

1) boost::bind의 첫번째 인자로 멤버 함수 또는 멤버 변수가 오면 boost::mem_fn을 적용한 효과와 같고, 2) _1 placeholder의 위치에  map의 pair가 인자로 들어간다. 1), 2)가 합쳐지면 i->second 가 Print().operator()의 인자로 들어가는 셈이 된다.

이렇게 하면 Print 를 vector<Elem> 에도 써먹을 수 있게 된다. 그전 같으면 map용 함수 객체와 vector나 list 용 함수 객체를 따로 작성해야 했는데, 이제 그럴 필요가 없다. 즉,

vector<Elem> v;
...
for_each(v.begin(), v.end(), Print());

이런 코드가 가능하다는 얘기지. ^^

그런데, 여전히

    boost::bind(Print(),
      boost::bind(&map<string, Elem>::value_type::second, _1))

이런 코드는 해석하기가 힘들다. bind에 어느 정도 인숙한 사람이 아니면. 좀 더 이해하기 쉽게 할 수는 없는 걸까? C++0x에서  lambda가 도입되면 좀 나아질래나 ?