
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