boost multi_index

/**
 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();
}
相關文章
相關標籤/搜索