如何从有序复合 boost::multi_index 中提取条件范围

问题描述

在以下简化示例中:

struct SalesRecord
{
    time_t date;
    std::string department;
    int sales_person_id;

    int num_sales;
    int total_num_sales;
};

typedef multi_index_container
    <
        SalesRecPtr,indexed_by
        <
            ordered_unique // 0
            <
                composite_key
                <
                    SalesRecPtr,member <SalesRecord,time_t,&SalesRecord::date>,std::string,&SalesRecord::department>,int,&SalesRecord::sales_person_id>
                >,composite_key_compare
                <
                    std::greater<time_t>,std::less<std::string>,std::less<int>
                >
            >,ordered_unique // 1
            <
                composite_key
                <
                    SalesRecPtr,&SalesRecord::sales_person_id>,&SalesRecord::date>
                >,composite_key_compare
                <
                    std::less<std::string>,std::less<int>,std::greater<time_t> // Could also be std::less  here
                >
            >
        >
    > SALES_RECORDS;

此 SALES_RECORDS 集合可能包含每天至少一次销售的人员和部门的销售记录。来自部门“Dep1”的人“A”可能在日期 1、3、4、5、20 有销售;

问。如何从这个集合中获取一个范围,在第 4 天后查找此人(“A”)、部门(“Dep1”)的所有记录? 这可用于在更正特定日期的销售数量后更新销售总数。 目前,我正在检索一个人的 equal_range 并迭代到所需的日期,这给我的搜索增加了不受欢迎的线性复杂性。

解决方法

tm     t{0,4,2,121,4}; // Mar 4,2021
time_t tt=mktime(&t);
int    person_id=5;

auto first=sales_records.get<1>().lower_bound(std::make_tuple("Dep1",person_id)),last =sales_records.get<1>().lower_bound(std::make_tuple("Dep1",person_id,tt));

更新:同样的事情可以用 range(示例中使用的 C++14)来完成:

auto p=sales_records.get<1>().range(
    [cmp=sales_records.get<1>().key_comp(),from=std::make_tuple("Dep1",person_id)   ]
    (const auto& x){return !cmp(x,from);},[cmp=sales_records.get<1>().key_comp(),to  =std::make_tuple("Dep1",tt)]
    (const auto& x){return cmp(x,to);});

但生成的代码确实比不带 range 的替代方法麻烦得多。