[multi_index] Indices interface type for overload resolution

Hi, I have currently template <typename Key, typename Value> std::vector<Key> keys(const std::map<Key, Value> &m) { ... } I'd like to write an overload that works also with the indices interface of multi_index_container. Suppose I have a multi_index_container with ordered unique indexes tagged "by_id" and "by_name". struct by_id {}; struct by_name {}; using BMI = multi_index::multi_index_container<Value, multi_index::indexed_by< multi_index::ordered_unique<by_id, multi_index::key<&Value::id>>, multi_index::ordered_unique<by_name, multi_index::key<&Value::name>>
;
BMI bmi; auto k = keys(bmi.get<by_name>()); Based on the documentation, I tried template< typename Tag,typename Value,typename IndexSpecifierList,typename Allocator > auto keys(const typename multi_index::index< multi_index::multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type& m) { typedef decltype(c.key_extractor()(*c.begin())) key_type; // A better definition would be welcome std::vector<key_type> result; result.reserve(c.size()); for (const auto &elem : c) { result.push_back(c.key_extractor()(elem)); } return result; } But the overload resolution fails. What should be the interface of keys in order to support indices interface of multi_index_container? Thank you, Christophe B

On Wed, Nov 20, 2019 at 2:51 PM Christophe B via Boost-users < boost-users@lists.boost.org> wrote:
template <typename Key, typename Value> std::vector<Key> keys(const std::map<Key, Value> &m) { ... }
I'd like to write an overload that works also with the indices interface of multi_index_container.
template <typename Key, typename Value>
std::vector<Key> keys(const std::map<Key, Value> &m) { ... }
I suspect that you only need to make your template a little more generic, something like (untested): template <typename C> std::vector<typename C::key_type> keys(const C& c) { std::vector<typename C::key_type> result; result.reserve(c.size()); for (const auto& entry : c) { result.emplace_back(entry.first); } return result; }

El 20/11/2019 a las 14:12, Christophe B via Boost-users escribió:
Hi,
I have currently
template <typename Key, typename Value> std::vector<Key> keys(const std::map<Key, Value> &m) { ... }
I'd like to write an overload that works also with the indices interface of multi_index_container.
[...]
template< typename Tag,typename Value,typename IndexSpecifierList,typename Allocator > auto keys(const typename multi_index::index< multi_index::multi_index_container<Value,IndexSpecifierList,Allocator>,Tag>::type& m) { typedef decltype(c.key_extractor()(*c.begin())) key_type; // A better definition would be welcome std::vector<key_type> result; result.reserve(c.size()); for (const auto &elem : c) { result.push_back(c.key_extractor()(elem)); } return result; }
But the overload resolution fails.
The second overload is not picked up because Tag, Value, etc. are being used in a nondeduced context: https://stackoverflow.com/questions/1268504/why-is-the-template-argument-ded... So, this approach won't get you anywhere. You have two options: 1. You can use the name of the actual class implementing ordered indices: template<typename... Args> auto keys(const boost::multi_index::detail::ordered_index<Args...>& c){...} THIS IS STRONGLY DISCOURAGED, because this name is not documented. Basically, you're relying on an implementation detail. Rather use: 2. With SFINAE and a little ingenuity you can have something like: template< typename Index, std::enable_if_t< sizeof(typename Index::key_type)&& sizeof(std::declval<const Index>().key_extractor()) >* =nullptr > auto keys(const Index& c) { using key_type=typename Index::key_type; std::vector<key_type> result; result.reserve(c.size()); for(const auto &elem:c){ result.push_back(c.key_extractor()(elem)); } return result; } Here, we're using SFINAE to activate the overload *only* when Index does have a nested key_type type and a key_extractor member function, which can be taken as a very certain bet that we're indeed dealing with a key-based Boost.MultiIndex index. This is, if you wish, poor man's pre-C++20 concepts. BTW, this overloads also picks hashed and ranked indices. Best, Joaquín M López Muñoz
participants (3)
-
Christophe B
-
Dominique Devienne
-
Joaquin M López Muñoz