본문 바로가기
프로그래밍/boost

boost::multi_index

by neive 2012. 3. 30.
728x90

 

 

boost::multi_index 는 키와 데이터 양쪽 모두가 키가 될 수 있는 형식의 컨테이너를 제공한다

흔한 사용 예는 '파티 시스템'에서 파티인덱스를 통해서 맴버들을 구할 수 있는게 보통의 map 이라면

파티원의 이름으로도 파티인덱스를 역추적한다던가 하는 것이 가능하다

또 하나의 예로는 '아이템 조합 시스템'에서 보통은 결과물 인덱스를 통해서 재료들을 알 수 있지만

multi_index 로는 재료를 가지고 만들 수 있는 모든 결과물의 인덱스를 역추적 할 수 있다

물론 map 으로도 구현 가능한 것들이지만 이렇게 되면 다수의 map 을 만들고 한개의 인덱스값을 공

유해야 한다

 

 

예제

// 가독성을 높이기 위해 풀어서 써놨으니 이해하는데는 도움이 될...듯?

struct SKey
{
	int nIndex;			// 오리지널 인덱스
	std::string sItemA;	// 재료 1
	std::string sItemB;	// 재료 2
	std::string sItemC;	// 재료 3
	std::string sReslt;	// 결과물

	SKey(int n, std::string s1, std::string s2, std::string s3, std::string sR)
		: nIndex(n), sItemA(s1), sItemB(s2), sItemC(s3), sReslt(sR) {}
};

struct SIndex{};
struct SItemA{};
struct SItemB{};
struct SItemC{};
struct SReslt{};

typedef boost::multi_index_container<
	SKey,
	boost::multi_index::indexed_by<
	boost::multi_index::ordered_unique<boost::multi_index::tag<SIndex>,  BOOST_MULTI_INDEX_MEMBER(SKey,int,nIndex)>,
	boost::multi_index::ordered_non_unique<boost::multi_index::tag<SItemA>,  BOOST_MULTI_INDEX_MEMBER(SKey,std::string,sItemA)>,
	boost::multi_index::ordered_non_unique<boost::multi_index::tag<SItemB>,BOOST_MULTI_INDEX_MEMBER(SKey,std::string,sItemB)>,
	boost::multi_index::ordered_non_unique<boost::multi_index::tag<SItemC>,BOOST_MULTI_INDEX_MEMBER(SKey,std::string,sItemC)>,
	boost::multi_index::ordered_non_unique<boost::multi_index::tag<SReslt>, BOOST_MULTI_INDEX_MEMBER(SKey,std::string,sReslt)> >
> SKey_set;


class CTest
{
	SKey_set m_IndexMap;

public:

	void Run()
	{
		m_IndexMap.insert(SKey(1, "OjA", "OjB", "OjC", "Res"));
		m_IndexMap.insert(SKey(2, "Potion", "Potion", "HolyWater", "HighPotion"));
		m_IndexMap.insert(SKey(3, "Sword", "Sword", "", "DuelSword"));

		{
			std::cout << "전체 반복" << std::endl;
			for(SKey_set::iterator it=m_IndexMap.begin(); it!=m_IndexMap.end(); it++)
				std::cout << it->sItemA.c_str() << std::endl;
		}

		{
			std::cout << "'키 순서' 타겟 반복" << std::endl;
			boost::multi_index::nth_index<SKey_set, 1>::type::iterator it;
			for(it = boost::multi_index::get<1>(m_IndexMap).begin(); it != boost::multi_index::get<1>(m_IndexMap).end(); it++)
				std::cout << it->sItemB.c_str() << std::endl;
		}

		{
			std::cout << "'특정 키' 타겟 반복" << std::endl;
			const SKey_set::index<SItemA>::type &typeKey = m_IndexMap.get<SItemA>();
			boost::multi_index::index<SKey_set, SItemA>::type::iterator it;
			for(it = typeKey.begin(); it != typeKey.end(); ++it)
				std::cout << it->sItemC.c_str() << std::endl;
		}

		{
			std::cout << "'키 순서' 타겟 find" << std::endl;
			int findIndex = 1;
			const SKey_set::nth_index<0>::type &typeKey = m_IndexMap.get<0>();	// <0> ~ <n>
			boost::multi_index::nth_index<SKey_set, 0>::type::iterator it = typeKey.find(findIndex);
			std::cout << "find " << it->sItemA.c_str() << std::endl;
		}

		{
			std::cout << "'특정 키' 타겟 find" << std::endl;
			std::string sFindName = "HolyWater";
			const SKey_set::index<SItemC>::type &typeKey = m_IndexMap.get<SItemC>();
			boost::multi_index::index<SKey_set, SItemC>::type::iterator it = typeKey.find(sFindName);
			std::cout << "find " << it->sReslt.c_str() << std::endl;
		}


		std::cout << "END" << std::endl;
	}

	CTest(void);
	virtual ~CTest(void);
};

 

 

결과


전체 반복
OjA
Potion
Sword


'키 순서' 타겟 반복
OjB
Potion
Sword


'특정 키' 타겟 반복
OjC
HolyWater

'키 순서' 타겟 find
find OjA
'특정 키' 타겟 find
find HighPotion

728x90

댓글