C++1x: std::map 초기화하기

C++03 을 쓰던 시절에 가졌던 불만 중 하나는 std::map 처럼 dictionary 타입을 쓸 때 선언 즉시 초기화하기 번잡한 것. 순서가 중요하지 않을 때 성능이 떨어지는 것도 그렇고. 예를 들어, “Jan” -> 1, “Feb” -> 2, …, “Dec” -> 12 와 같은 관계를 표현하고 싶을 때 C++03 에서 std::map 에 간단히 표현할 방법은 없다. 추가적인 초기화함수를 선언해서 써야한다.

const static std::map<std::string, int> kMonths
    = InitializeMonthDict();
static std::map<std::string, int> InitializeMonthDict() {
  std::map<std::string, int> rv;
  rv.insert(std::make_pair("Jan", 1));
  rv.insert(std::make_pair("Feb", 2));
  // ...
  return rv;
}

혹은 이걸 초기화한 값을 갖는 operator overloading된 구조체/클래스를 선언하거나.

C++03이더라도 boost 를 쓸 수 있다면 boost::assign map_list_of 를 써서 다음과 같이 쓸 순 있다:

#include <boost/assign/list_of.hpp>
#include <map>
const static std::map<std::string, int> kMonths
    = boost::map_list_of("Jan", 1)("Feb, 2")
      // ...
      ("Dec", 12);

이런 식으로 표현하는게 요즘 언어들 (예를 들어 Python 혹은 JSON 표현형) 과 비교하면 너무 번잡하다. 예를 들어 Python으로 표현하면:

kMonths = {
  "Jan": 1,
  "Feb": 2,
  # ...
  "Dec": 12,
}

하지만 C++11 을 쓰면 이건 초기화 목록을 쓰는 간단한 문법으로 바뀐다:

#include <map>  // unordered_map 을 쓸수도
const static std::map<std::string, int> kMonths
    = {{"Jan", 1"}, {"Feb", 2}, /* ... */ {"Dec", 12},};

덕분에 요즘은 테이블 룩업 류 (예를 들어 enum -> 함수 맵) 처리할 땐 편하게 짜고 있는 듯 하다.