You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用boost::multi_index复合键成员函数时的查询编译错误问题

Boost.MultiIndex查询编译错误解决方案

问题场景

定义了如下容器:

using KeyValue = mutable_pair<Key, Value>;
using MyContainer = boost::multi_index_container<
    KeyValue,
    boost::multi_index::indexed_by<
        boost::multi_index::hashed_unique<
            boost::multi_index::tag<KeyValueTag>,
            boost::multi_index::composite_key<
                KeyValue,
                boost::multi_index::const_mem_fun<KeyValue::first_type, unsigned int, &KeyValue::first_type::foo>,
                boost::multi_index::const_mem_fun<KeyValue::first_type, unsigned int, &KeyValue::first_type::bar>,
                boost::multi_index::const_mem_fun<KeyValue::first_type, unsigned int, &KeyValue::first_type::baz>,
            >
        >,
        boost::multi_index::hashed_non_unique<
            boost::multi_index::tag<BazTag>,
            boost::multi_index::const_mem_fun<KeyValue::first_type, unsigned int, &KeyValue::first_type::baz>
        >,
        boost::multi_index::hashed_non_unique<
            boost::multi_index::tag<BarTag>,
            boost::multi_index::const_mem_fun<KeyValue::first_type, unsigned int, &KeyValue::first_type::bar>
        >
    >
>;

其中mutable_pair是Boost官方提供的映射示例类型,Key类包含foo、bar、baz的const成员访问函数。

容器编译正常,但执行查询操作时:

MyContainer c;
const auto& byBaz = c.get<BazTag>();
const auto it = byBaz.find(11);
// 或
const auto [beg, end] = byBaz.equal_range(11);

出现编译错误:

<long instantiation template error>
in mem_fun.hpp:58:23: error: no match for ‘operator*’ (operand type is ‘const mutable_pair<Key, Value>’)
   58 |     return operator()(*x);

错误原因

你使用的const_mem_fun提取器默认会尝试解引用容器元素(KeyValue即mutable_pair<Key, Value>)来获取成员函数所属的Key对象,但mutable_pair没有为const对象重载operator*。当查询const索引时,元素是const修饰的,导致无法调用非const的operator*,从而触发编译错误。

解决方案

方案1:为mutable_pair添加const版本的operator*

修改mutable_pair的定义,补充const重载的operator*:

template <typename T1, typename T2>
struct mutable_pair {
    T1 first;
    T2 second;

    // 保留原有非const版本(如果已定义)
    mutable_pair& operator*() { return *this; }
    // 添加const版本
    const mutable_pair& operator*() const { return *this; }

    // 其他原有成员...
};

方案2:修正提取器写法,直接访问first成员

不依赖operator*,直接提取KeyValue的first成员再调用其成员函数。以下是几种实现方式:

方式A:使用Boost.Bind

以BazTag索引为例:

boost::multi_index::hashed_non_unique<
    boost::multi_index::tag<BazTag>,
    boost::multi_index::transformed<
        boost::bind(&Key::baz, boost::bind(&KeyValue::first, _1))
    >
>

方式B:使用C11 Lambda(需Boost.MultiIndex支持C11)

boost::multi_index::hashed_non_unique<
    boost::multi_index::tag<BazTag>,
    boost::multi_index::key_extractor<decltype([](const KeyValue& kv) { return kv.first.baz(); })>(
        [](const KeyValue& kv) { return kv.first.baz(); }
    )
>

方式C:自定义提取器结构体

// 定义提取器
struct BazExtractor {
    unsigned int operator()(const KeyValue& kv) const {
        return kv.first.baz();
    }
};

// 索引定义
boost::multi_index::hashed_non_unique<
    boost::multi_index::tag<BazTag>,
    BazExtractor
>

两种方案均可解决问题:方案1仅需修改mutable_pair,实现简单;方案2更直观,避免依赖mutable_pair的operator*行为。


内容的提问来源于stack exchange,提问作者Santiago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:00:31