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 -> 함수 맵) 처리할 땐 편하게 짜고 있는 듯 하다.