简单的答案当然是std::unordered_map。但是,为了获得更多功能和自动索引一致性,我们可以使用boost::multi_index_container。
例如:
namespace bmi = boost::multi_index;
// Define a custom container type
using my_map = boost::multi_index_container<
// It holds StringValue objects
StringValue,
bmi::indexed_by<
// first index is called by_string, is a unique hashed index with constant time lookuo
bmi::hashed_unique<bmi::tag<by_string>, bmi::member<StringValue, std::string, &StringValue::str>>,
// second index is called by_value, is a unique hashed index with constant time lookup
bmi::hashed_unique<bmi::tag<by_value>, bmi::member<StringValue, int, &StringValue::value>>,
// second index is called ordered_by_value, is a unique ordered index with logarithmic time lookup
bmi::ordered_unique<bmi::tag<ordered_by_value>, bmi::member<StringValue, int, &StringValue::value>>
>
>;
在本例中,my_map 被定义为一个容器:
完整示例:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/format.hpp>
#include <string>
#include <iostream>
#include <iomanip>
#include <cassert>
#include <type_traits>
// define a value object
struct StringValue
{
std::string str;
int value;
};
// provide a way to stream the pair to an ostream
std::ostream& operator <<(std::ostream& os, StringValue const& sv)
{
static const char fmt[] = R"__({ "str": %1%, "value": %2% })__";
return os << boost::format(fmt) % std::quoted(sv.str) % sv.value;
}
struct by_string
{
};
struct by_value
{
};
struct ordered_by_value
{
};
namespace bmi = boost::multi_index;
// Define a custom container type
using my_map = boost::multi_index_container<
// It holds StringValue objects
StringValue,
bmi::indexed_by<
// first index is called by_string, is a unique hashed index with constant time lookuo
bmi::hashed_unique<bmi::tag<by_string>, bmi::member<StringValue, std::string, &StringValue::str>>,
// second index is called by_value, is a unique hashed index with constant time lookup
bmi::hashed_unique<bmi::tag<by_value>, bmi::member<StringValue, int, &StringValue::value>>,
// second index is called ordered_by_value, is a unique ordered index with logarithmic time lookup
bmi::ordered_unique<bmi::tag<ordered_by_value>, bmi::member<StringValue, int, &StringValue::value>>
>
>;
template<class Array>
struct ArrayEmitter
{
const Array& array;
friend std::ostream& operator<<(std::ostream& os, ArrayEmitter const& em) {
const char* sep = " ";
os << "[";
for (auto&& item : em.array) {
os << sep << item;
sep = ", ";
}
return os << " ]";
}
};
template<class Array>
auto emit_as_array(Array&& arr)
{
return ArrayEmitter<std::remove_cv_t<Array>> { arr };
}
int main()
{
my_map mm { { "B", 3 }, { "D", 1 }, { "A", 4 }, { "C", 2 } };
// assert that we can't violate the indecies
auto ib = mm.insert(StringValue{"E", 1});
assert(ib.second == false);
// iterate by string
std::cout << "print by value index:\n";
std::cout << emit_as_array(mm.get<by_string>()) << std::endl;
std::cout << "\nprint by value index unordered:\n";
std::cout << emit_as_array(mm.get<by_value>()) << std::endl;
std::cout << "\nprint by value index ordered:\n";
std::cout << emit_as_array(mm.get<ordered_by_value>()) << std::endl;
std::cout << "\nfind an element by value in constant time:\n";
auto&& name = mm.get<by_value>().find(2)->str;
std::cout << name << std::endl;
}
预期输出:
print by value index:
[ { "str": "B", "value": 3 }, { "str": "D", "value": 1 }, { "str": "A", "value": 4 }, { "str": "C", "value": 2 } ]
print by value index unordered:
[ { "str": "B", "value": 3 }, { "str": "D", "value": 1 }, { "str": "A", "value": 4 }, { "str": "C", "value": 2 } ]
print by value index ordered:
[ { "str": "D", "value": 1 }, { "str": "C", "value": 2 }, { "str": "B", "value": 3 }, { "str": "A", "value": 4 } ]
find an element by value in constant time:
C
文档:
http://www.boost.org/doc/libs/1_62_0/libs/multi_index/doc/tutorial/index.html