简单的答案当然是 std::unordered_map
。然而,为了获取更多功能和自动索引一致性,我们可以使用 boost::multi_index_container
。
例如:
namespace bmi = boost::multi_index;
using my_map = boost::multi_index_container<
StringValue,
bmi::indexed_by<
bmi::hashed_unique<bmi::tag<by_string>, bmi::member<StringValue, std::string, &StringValue::str>>,
bmi::hashed_unique<bmi::tag<by_value>, bmi::member<StringValue, int, &StringValue::value>>,
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>
struct StringValue
{
std::string str;
int value;
};
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;
using my_map = boost::multi_index_container<
StringValue,
bmi::indexed_by<
bmi::hashed_unique<bmi::tag<by_string>, bmi::member<StringValue, std::string, &StringValue::str>>,
bmi::hashed_unique<bmi::tag<by_value>, bmi::member<StringValue, int, &StringValue::value>>,
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 } };
auto ib = mm.insert(StringValue{"E", 1});
assert(ib.second == false);
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