使用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
相关产品推荐
相关产品推荐

