Lookup on nested boost multi_index_container

前端 未结 3 2045
谎友^
谎友^ 2021-01-27 03:09

Consider following code

struct VersionData
{
    VersionData();
    VersionData(VersionData&& rhs);
    int     m_versionId;
    int     m_weight;
    in         


        
3条回答
  •  北恋
    北恋 (楼主)
    2021-01-27 04:06

    So indeed, instead of using nested containers, like that (live on Coliru)

    You could/should implement it as a single /table/ (after all, this is a table with several indices):

    Live On Coliru

    #include 
    #include 
    #include 
    #include 
    
    namespace bmi = boost::multi_index;
    
    struct VersionRecord {
        int  m_subdeliveryGroupId;
        int  m_retargetingId;
        int  m_versionId;
        int  m_weight;
        int  m_pId;
        bool m_hdi;
    
        friend std::ostream& operator<<(std::ostream& os, VersionRecord const& record) {
            return os << "{ " << record.m_subdeliveryGroupId << " " << record.m_retargetingId << " "
                << record.m_versionId << " " << record.m_weight << " " << record.m_pId << " " << record.m_hdi << " }";
        }
    };
    
    typedef boost::multi_index_container<
        VersionRecord,
        bmi::indexed_by<
            bmi::ordered_unique<
                bmi::tag,
                bmi::composite_key<
                    VersionRecord,
                    bmi::member,
                    bmi::member
                >
            >,
            bmi::ordered_non_unique<
                bmi::tag,
                bmi::member
            >
        >
    > VersionTable;
    
    #include 
    #include 
    
    int main() {
    
        auto table = VersionTable { 
            { 21, 10,                1,  100, 123, false },
            { 9,  27,                2,  90,  123, false },
            { 12, 25,                3,  110, 123, true  },
            { 10, 33, /*version 8:*/ 8,  80,  123, false },
            { 4,  38,                5,  101, 124, false },
            { 33, 7,                 6,  91,  124, false },
            { 34, 27,                7,  111, 124, true  },
            { 9,  11, /*version 8:*/ 8,  81,  124, false },
            { 0,  12,                9,  99,  125, false },
            { 35, 39, /*version 8:*/ 8,  89,  125, false },
            { 15, 15,                11, 109, 125, true  },
            { 25, 32, /*version 8:*/ 8,  79,  125, false },
        };
    
        // debug table output
        assert(table.size()==12);
        for (auto& record : table) std::cout << record << "\n";
    
        // so now you can do:
        auto& idx = table.get();
    
        std::cout << "---\nQuerying for version id 8:\n";
        for (auto& record : boost::make_iterator_range(idx.equal_range(8)))
            std::cout << record << "\n";
    }
    

    Which prints:

    { 0 12 9 99 125 0 }
    { 4 38 5 101 124 0 }
    { 9 11 8 81 124 0 }
    { 9 27 2 90 123 0 }
    { 10 33 8 80 123 0 }
    { 12 25 3 110 123 1 }
    { 15 15 11 109 125 1 }
    { 21 10 1 100 123 0 }
    { 25 32 8 79 125 0 }
    { 33 7 6 91 124 0 }
    { 34 27 7 111 124 1 }
    { 35 39 8 89 125 0 }
    ---
    Querying for version id 8:
    { 25 32 8 79 125 0 }
    { 35 39 8 89 125 0 }
    { 10 33 8 80 123 0 }
    { 9 11 8 81 124 0 }
    

    Alternatively, you can bolt an intrusive container on top of the VersionsData records. This however, complicates the design (you either have to use auto_unlink node hooks (sacrificing thread safety control) or you have to make sure the containers are in synch all the time.

提交回复
热议问题