boost::multi_index_container支持构建容器,该容器维护一个或多个具有不同排序和访问语义的索引,例如关系数据库。
我使用带有复合键的boost::multi_index_container来处理类似这样的事情:

struct Person {
    Person(int id, string name):
        m_id(id),
        m_name(name)
    {
    }

    int m_id;
    string m_name;
};

typedef multi_index_container<
    Person,
    indexed_by<
        ordered_unique<
            member<Person, int, &Person::m_id>
        >,
        ordered_unique<
            composite_key<
                Person,
                member<Person, string, &Person::m_name>,
                member<Person, int, &Person::m_id>
            >
         >
    >
> Roster;

int main()
{
    Roster r;
    r.insert(Person(1, "Tom"));
    r.insert(Person(2, "Jack"));
    r.insert(Person(3, "Tom"));
    r.insert(Person(4, "Leo"));

    /* The distinct count of name must be 3, and how to get it? */
}

有什么办法可以像关系数据库那样获得boost::multi_index_container中非唯一索引键的独特的计数?以及如何获得Person::name复合键(RosterPerson::m_name)的第一个键(Person::m_id)的独特计数?
谢谢!

编辑:
还是只是一种方法来迭代唯一的第一把 key ?这样我们就可以得到不同数量的第一把 key 。

最佳答案

您可以利用以下事实:您知道复合索引首先是m_name的顺序。

这意味着您可以在其上运行标准的“唯一”,而无需其他排序步骤:

    size_t unique_names = boost::size(r.get<by_name_id>()
            | transformed([](Person const& p) -> std::string const& { return p.m_name; })
            | uniqued
        );

这可能是一个很好的时间/存储权衡。

演示版

Live On Coliru
#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>

struct Person {
    Person(int id, std::string name):
        m_id(id),
        m_name(name)
    {
    }

    int m_id;
    std::string m_name;
};

namespace bmi = boost::multi_index;

typedef boost::multi_index_container<
    Person,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::member<Person, int, &Person::m_id>
        >,
        bmi::ordered_unique<
            bmi::tag<struct by_name_id>,
            bmi::composite_key<
                Person,
                bmi::member<Person, std::string, &Person::m_name>,
                bmi::member<Person, int, &Person::m_id>
            >
        >
    >
> Roster;

#include <iostream>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>

using boost::adaptors::transformed;
using boost::adaptors::uniqued;

int main()
{
    Roster r;
    r.insert(Person(1, "Tom"));
    r.insert(Person(2, "Jack"));
    r.insert(Person(3, "Tom"));
    r.insert(Person(4, "Leo"));

    size_t unique_names = boost::size(r.get<by_name_id>()
            | transformed([](Person const& p) -> std::string const& { return p.m_name; })
            | uniqued
        );

    std::cout << unique_names;
}

版画
3

10-04 15:07