C++14下Boost Multi Index模板类索引转标签与遍历实现问询
Alright, let's tackle this problem step by step. You're working with a template class CrMultiIndex wrapping a Boost Multi Index container (your GlobalHash type), and need to map index positions to human-readable tags, plus iterate over all indexes during initialization in C++14. Here's how to pull this off:
1. Core Approach: Compile-Time Index Traversal
Boost Multi Index containers expose a static member n_indices that tells you how many indexes are defined. We can use compile-time index sequences (via Boost's utilities, since C++14 doesn't have std::index_sequence in the standard library) to iterate over each index position, then capture its type information to generate tags.
2. Implementing the Tag Collection
First, we'll add a member to store our index tags, then write a helper function to populate it during initialization. We'll also use Boost.TypeIndex instead of raw typeid to get more readable, compiler-agnostic type names (though you can use typeid if you don't mind mangled strings).
Here's the full implementation:
#include <vector> #include <string> #include <boost/multi_index_container.hpp> #include <boost/type_index.hpp> #include <boost/utility/index_sequence.hpp> template <typename GlobalHash> class CrMultiIndex { private: GlobalHash container_; std::vector<std::string> index_tags_; // Helper to collect tags using compile-time index sequence template <std::size_t... Indexes> void collect_index_tags(boost::index_sequence<Indexes...>) { index_tags_.reserve(GlobalHash::n_indices); // Use a dummy array to expand the parameter pack in C++14 using swallow = int[]; (void)swallow{0, ( // Capture readable type name for each index index_tags_.push_back( boost::typeindex::type_id<typename GlobalHash::template nth_index<Indexes>::type>() .pretty_name() ), 0 )...}; } public: // Initialize tags in constructor CrMultiIndex() { collect_index_tags(boost::make_index_sequence<GlobalHash::n_indices>{}); } // Or use an Init function if you need delayed initialization void Init() { index_tags_.clear(); collect_index_tags(boost::make_index_sequence<GlobalHash::n_indices>{}); } // Map index number to tag string const std::string& n_to_tag(std::size_t index) const { static const std::string empty_tag = ""; if (index >= index_tags_.size()) { return empty_tag; // Handle out-of-bounds gracefully } return index_tags_[index]; } // Access the underlying container if needed GlobalHash& get_container() { return container_; } const GlobalHash& get_container() const { return container_; } };
3. Alternative: Using Boost.MPL for Traversal
If you prefer using Boost.MPL instead of index sequences, you can achieve the same result with boost::mpl::for_each to iterate over index positions:
#include <boost/mpl/for_each.hpp> #include <boost/mpl/range_c.hpp> // Inside CrMultiIndex's private section: struct IndexTagCollector { std::vector<std::string>& tags; explicit IndexTagCollector(std::vector<std::string>& t) : tags(t) {} template <std::size_t N> void operator()(boost::mpl::integral_c<std::size_t, N>) const { using IndexType = typename GlobalHash::template nth_index<N>::type; tags.push_back( boost::typeindex::type_id<IndexType>().pretty_name() ); } }; // Update collect_index_tags: void collect_index_tags() { index_tags_.reserve(GlobalHash::n_indices); boost::mpl::for_each<boost::mpl::range_c<std::size_t, 0, GlobalHash::n_indices>>( IndexTagCollector{index_tags_} ); }
Key Notes
GlobalHash::n_indices: This is a static member provided by Boost Multi Index containers, giving you the total number of indexes at compile time.- Type Name Readability: Raw
typeid(T).name()returns compiler-mangled strings (e.g.,N5boost11multi_index...). Boost.TypeIndex'spretty_name()converts this to human-readable text likeboost::multi_index::hashed_unique<...>. - Error Handling: The
n_to_tagfunction returns an empty string for out-of-bounds indexes—adjust this to throw an exception or handle errors as needed for your use case.
内容的提问来源于stack exchange,提问作者yaron

