/** boost 多索引容器的通常使用 這裏使用google 的gmock 庫來驗證對boost 多索引模板的使用,並驗證。 這裏是手敲的,可能會有一些字符敲錯的狀況,編譯錯誤的放,修改一下,同時連接gmock庫就能夠正常運行了。 固然還須要連接boost 的相關庫 **/ #include <stdint.h> #include <gtest/gtest.h> #include <gmock/gmock.h> #include <boost/multi_index_container.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/member.hpp> #include <boost/multi_index/composite_key.hpp> #include <boost/multi_index/global_fun.hpp> // 多索引的結構或者類 struct stru_AccountFeeIncre { int64_t nAccountID; int32_t nGoodsID; int32_t nGoodsGroupID; int32_t nFeeMode; int32_t nTradeMode; double dFeeValue; }; // 爲索引的Key 定義一個標誌類型,相似std::map 的Key struct tagGoodsID {}; struct tagGoodsGroupID {}; // 聲明多索引結構,主要綁定索引類型能夠與指定成員的一一映射 using MultiIndexFeeIncre = boost::multi_index::multi_index_container< stru_AccountFeeIncre, // 數據結構,用於索引的對象 boost::multi_index::indexed_by< // 建立索引,能夠是一個或者多個。分別以',' 分隔 // 建立惟一索引,不容許插入該字段的值相同的兩個對象到此容器中。 boost::multi_index::ordered_unique< boost::multi_index::tag<tagGoodsID>, // 索引標籤 BOOST_MULTI_INDEX_MEMBER(struAccountFeeIncre, int32_t, nGoodsID) // 該索引綁定的成員 >, // 建立非惟一索引,容許多個相同的值到此容器中 boost::multi_index::ordered_non_unique< boost::multi_index::tag<tagGoodsGroupID>, BOOST_MULTI_INDEX_MEMBER(stru_AccountFeeIncre, int32_t, nGoodsGroupID) > > >; using C_ITER_FEE_INCRE = MultiIndexFeeIncre::const_iterator; using PAIR_RANGE_FEE_INCRE = std::pair<C_ITER_FEE_INCRE, C_ITER_FEE_INCRE>; using C_ITER_ID_FEE_INCRE = MultiIndexFeeIncre::index<tagGoodsID>::type::const_iterator; using C_ITER_GROUP_FEE_INCRE = MultiIndexFeeIncre::index<tagGoodsGroupID>::type::const_iterator; using PAIR_RANGE_GROUP_FEE_INCRE = std::pair<C_ITER_GROUP_FEE_INCRE, C_ITER_GROUP_FEE_INCRE>; // 定義多索引容器實例 static MultiIndexFeeIncre s_multiAccountFeeIncre; // 定義容器的索引實例的引用 - 非const 版本 static MultiIndexFeeIncre::index<tagGoodsID>::type &INDEX_ID_FEE_INCRE = s_multiAccountFeeIncre.get<tagGoodsID>(); static MultiIndexFeeIncre::index<taggoodsGroupID>::type &INDEX_GROUP_FEE_INCRE = s_multiAccountFeeIncre.get<tagGoodsGroupID>(); // 定義容器的索引實例的引用 - const 版本 static const MultiIndexFeeIncre::index<tagGoodsID>::type &C_INDEX_ID_FEE_INCRE = s_multiAccountFeeIncre.get<tagGoodsID>(); static const MultiIndexFeeIncre::index<tagGoodsgroupID>::type &C_INDEX_GROUP_FEE_INCRE = s_multiAccountFeeIncre.get<tagGoodsGroupID>(); // template 版本 MultiIndexFeeIncre::template index<tagGoodsID>::type &TPLT_INDEX_ID = s_multiAccountFeeIncre.template get<taggoodsID>(); MultiIndexFeeIncre::template index<tagGoodsGroupID>::type &TPLT_INDEX_GROUP = s_multiAccountFeeIncre.template get<tagGoodsGroupID>(); TEST(TestBoostUse, MultiIndex) { const int32_t GROUP_ID_01 = 1; const int32_t GROUP_ID_02 = 2; int64_t nExpectSize = 0; EXPECT_EQ(nExpectSize, s_multiAccountFeeIncre.size()); int64_t nGoodsID = 1; stru_AccountFeeIncre stFeeIncre; stFeeIncre.nAccountID = 1; stFeeIncre.nGoodsID = nGoodsID; stFeeIncre.nGoodsGroupID = GROUP_ID_01; stFeeIncre.nFeeMode = 0; stFeeIncre.nTradeMode = 1; stFeeIncre.dFeeValue = 0.5; // 商品組1 int32_t nExpectSizeGroupID_1 = 0; // 插入一條 s_multiAccountFeeIncre.emplace(stFeeIncre); ++nExpectSize; ++nExpectSizeGroupID_1; EXPECT_EQ(nExpectSize, s_multiAccountFeeIncre.size()); // 插入與惟一索引相同的值的對象,插入失敗 s_multiAccountFeeIncre.emplace(stFeeIncre); EXPECT_EQ(nExpectSize, s_multiAccountFeeIncre.size()); // 插入一條 ++nGoodsID; stFeeIncre.nGoodsID = nGoodsID; stFeeIncre.nGoodsGroupID = GROUPID_01; s_multiAccountFeeIncre.emplace(stFeeIncre); ++nExpectSize; ++nExpectSizeGroupID_1; EXPECT_EQ(nExpectSize, s_multiAccountfeeIncre.size()); // 插入一條 ++nGoodsID; stFeeIncre.nGoodsID = nGoodsID; stFeeIncre.nGoodsGroupID = GROUP_ID_01; s_multiAccountFeeIncre.emplace(stFeeIncre); ++nExpectSize; ++nExpectSizeGroupID_1; EXPECT_EQ(nExpectSize, s_multiAccountFeeIncre.size()); // 插入到另外一個商品組 int32_t nExpectSizeGroupID_2 = 0; ++nGoodsID; stFeeIncre.nGoodsID = nGoodsID; stFeeIncre.nGoodsGroupID = GROUP_ID_02; s_multiAccountFeeIncre.emplace(stFeeIncre); ++nExpectSize; ++nExpectSizeGroupID_2; EXPECT_EQ(nExpectSize, s_multiAccountFeeIncre.size()); // 插入一條 ++nGoodsID; stFeeIncre.nGoodsID = nGoodsID; stFeeIncre.nGoodsGroupID = GROUP_ID_02; s_multiAccountFeeIncre.emplace(stFeeIncre); ++nExpectSize; ++nExpectSizeGroupID_2; EPXECT_EQ(nEpxectSize, s_multiAccountFeeIncre.size()); // 查詢 do { // 惟一索引的查詢,結果僅有一條記錄 int nTempGoodsID = 1; C_ITER_ID_FEE_INCRE c_iter_id = INDEX_ID_FEE_INCRE.find(nTempGoodsID); ASSERT_NE(c_iter_id, INDEX_ID_FEE_INCRE.end()); // 非惟一索引的查詢,結果爲一組記錄 PAIR_RANGE_GROUP_FEE_INCRE range = TPLT_INDEX_GROUP.equal_range(GROUP_ID_01); int nTempSize = 0; for (auto it = range.first; it != range.second; ++it) { EXPECT_EQ(GROUP_ID_01, it->nGoodsGroupID); ++nTempSize; } EXPECT_EQ(nExpectSizeGroupID_1, nTempSize); } while (false); // 修改 do { // 拷貝副本 MultiIndexFeeIncre bak_multiAccountFeeIncre = s_multiAccountFeeIncre; int32_t bakExpectSize = nExpectSize; int32_t nTempGoosdID = 1; C_ITER_ID_FEE_INCRE c_iter_id = bak_multiAccountFeeIncre.get<tagGoodsID>().find(nTempGoodsID); EXPECT_NE(c_iter_id, bak_multiAccountFeeIncre.get<tagGoodsID>().end()); if (c_iter_id == bak_multiAccountFeeIncre.get<tagGoodsID>().end()) { break; } stru_AccountFeeIncre newObj; // 未設置值使用內存隨機值便可 newObj.nGoodsID = c_iter_id->nGoodsID; // 惟一性主鍵不修改 newObj.nGoodsGroupID = nExpectSizeGroupID_2; // 商品組ID改到2 非惟一性主鍵修改 bool bResTemp = bak_multiAccountfeeIncre.replace(c_iter_id, newObj); EXPECT_TRUE(bResTemp); EXPECT_EQ(bakExpectSize, bak_multiAccountFeeIncre.size()); } while (false); do { // 拷貝副本 MultiIndexFeeIncre bak_multiAccountFeeIncre = s_multiAccountFeeIncre; int32_t bakExpectSize = nExpectSize; int32_t nTempGoodsID = 1; C_ITER_ID_FEE_INCRE c_iter_id = bak_multiAccountFeeIncre.get<tagGoodsID>().find(nTempGoodsID); EXPECT_NE(c_iter_id, bak_multiAccountFeeIncre.get<tagGoodsID>().end()); if (c_iter_id == bak_multiAccountFeeIncre.get<tagGoodsID>().end()) { break; } stru_AccountFeeIncre newObj; newObj.nGoodsID = 23487954; // 修改惟一性主鍵 newObj.nGoodsGroupID = c_iter_id->nGoodsGroupID; // 非惟一性主鍵不修改 bool bResTemp = bak_multiAccountFeeIncre.replace(c_iter_id, newObj); EXPECT_TRUE(bResTemp); EXPECT_EQ(bakExpectSize, bak_multiAccountFeeIncre.size()); } while (false); // 刪除 do { // 拷貝副本 MultiIndexFeeIncre bak_multiAccountFeeIncre = s_multiAccountFeeIncre; int32_t bakExpectSize = nExpectSize; int32_t bakExpectSizeGroupID_1 = nExpectSizeGroupID_1; // 先刪除商品組1 中的一個商品 int nTempGoodsID = 1; C_ITER_ID_FEE_INCRE c_iter_id = bak_multiAccountFeeIncre.get<tagGoodsID>().find(nTempGoodsID); ASSERT_NE(c_iter_id, bak_multiAccountFeeIncre.get<taggoodsID>().end()); bak_multiAccountFeeIncre.erase(c_iter_id); --bakExpectSize; --bakExpectSizeGroupID_1; EXPECT_EQ(bakExpectSize, bak_multiAccountFeeIncre.size()); // 刪除商品組1 的元素 EXPECT_EQ(bakExpectSize, bak_multiAccountFeeIncre.get<tagGroupID>().size()); EXPECT_EQ(bakExpectSize, bak_multiAccountFeeIncre.get<tagGoodsGroupID>().size()); bak_multiAccountFeeIncre.template get<tagGoodsGroupID>().erase(GROUP_ID_01); bakExpectSize -= bakExpectSizeGroupID_1; bakExpectSizeGroupID_1 = 0; EXPECT_EQ(bakExpectSize, bak_multiAccountFeeIncre.size()); } while (false); do { // 拷貝副本 MultiIndexFeeIncre bak_multiAccountFeeIncre = s_multiAccountFeeIncre; int32_t bakExpectSize = nExpectSize; int32_t bakExpectSizeGroupID_2 = nExpectSizeGroupID_2; // 刪除商品組2 的元素 bak_multiAccountFeeIncre.template get<tagGoodsGroupID>().erase(GROUP_ID_02); bakExpectSize -= bakExpectSizeGroupID_2; bakExpectSizeGroupID_2 = 0; EXPECT_EQ(bakExpectSize, bak_multiAccountFeeIncre.size()); } while (false); do { // 拷貝副本 MultiIndexFeeIncre bak_multiAccountFeeIncre = s_multiAccountFeeIncre; int32_t bakGoodsID = nGoodsID; int32_t bakExpectSize = nExpectSize; // 按惟一性主鍵: 商品ID 進行刪除 do { bak_multiAccountFeeIncre.template get<tagGoodsID>().erase(bakGoodsID); --bakExpectSize; EXPECT_EQ(bakExpectSize, bak_multiAccountFeeIncre.size()); } while (--bakGoodsID > 0); } while (false); } int main(int argc, char *argv[]) { testing::InitGoodsMock(&argc, argv); return RUN_ALL_TESTS(); }