Dictionary 容器平面图和std::string\u视图
一段时间以来,我一直在使用Boost的flat_map作为我的go to associative集合,原因在他们的文档介绍中被引用,最初的事实是它在编译器的std实现之前提供了更新的特性,并且在不同的平台上都是一样的 现在,我想开始使用string_视图来防止复制字符串,当这些字符串从较大输入的子字符串中获取时。string_视图指向较大字符串中的一系列字符,而无需将它们复制到新的std::string实例中 在获取地图时,我回忆起Boost.Container的另一个渐进特性,我过去喜欢的是保形键,在保形键中,您可以使用与存储的键进行正确比较的任何东西,而不是转换为实际的键类型 但现在我在文档中找不到任何关于这一点的提及。从C++14开始,我就知道std::map现在可以做到这一点,但我更愿意将平面映射用于小集合Dictionary 容器平面图和std::string\u视图,dictionary,boost,string-view,Dictionary,Boost,String View,一段时间以来,我一直在使用Boost的flat_map作为我的go to associative集合,原因在他们的文档介绍中被引用,最初的事实是它在编译器的std实现之前提供了更新的特性,并且在不同的平台上都是一样的 现在,我想开始使用string_视图来防止复制字符串,当这些字符串从较大输入的子字符串中获取时。string_视图指向较大字符串中的一系列字符,而无需将它们复制到新的std::string实例中 在获取地图时,我回忆起Boost.Container的另一个渐进特性,我过去喜欢的是保
几年前,如果boost::flat_map::insert等中没有显示这种灵活性,我会看到什么。?最新的编译器现在可以使用哪些优秀的平面集合?仅在Boost.Container中添加了对多态查找函数的支持。如果一切正常,则应使用Boost 1.68发布 同时,您可以模拟具有有序std::vector和std::lower_边界的平面关联容器
仅在Boost.Container中添加了对多态查找函数的支持。如果一切正常,则应使用Boost 1.68发布 同时,您可以模拟具有有序std::vector和std::lower_边界的平面关联容器
可能这不是您所指的,但如果您使用std::string_视图作为键类型,则所有操作都已通过到std::string_视图的隐式转换工作: 相反 在这里,您实际上需要使用一个支持兼容密钥查找的容器。滚动一个不需要太复杂: 这里有一个: 它精确地支持与第一个场景相反的情况,给定了std::less的比较器:
可能这不是您所指的,但如果您使用std::string_视图作为键类型,则所有操作都已通过到std::string_视图的隐式转换工作: 相反 在这里,您实际上需要使用一个支持兼容密钥查找的容器。滚动一个不需要太复杂: 这里有一个: 它精确地支持与第一个场景相反的情况,给定了std::less的比较器:
异构查找和兼容键确实是boost部分中存在的功能,例如boost多索引。也许这些关键词可以帮助你找到你似乎记得的东西。否则,Andrey的答案是excellentMulti index:这可能就是我看到它的地方,因为我也使用了它。谢谢。异构查找和兼容键确实是boost部分中存在的功能,例如boost多索引。也许这些关键词可以帮助你找到你似乎记得的东西。否则,Andrey的答案是excellentMulti index:这可能就是我看到它的地方,因为我也使用了它。谢谢。为什么您需要元素顺序而不只是使用less?因为std::less不是多态函数对象。它要求其参数与其模板参数相同。实际上,由于C++14 std::less是等价的,因此std::less是多态的。但是您仍然无法使用它,因为您需要访问元素类型的成员,而std::less会尝试将整个元素类型与键进行比较。为什么您需要元素顺序而不是仅使用less?因为std::less不是多态函数对象。它要求其参数与其模板参数相同。实际上,由于C++14 std::less是等价的,因此std::less是多态的。但是您仍然不能使用它,因为您需要访问元素类型的成员,而std::less会尝试将整个元素类型与键进行比较。我认为使用字符串视图作为键类型是一个非常糟糕的主意,因为它不拥有存储。不过,如果你能控制事物的添加方式,有限的曝光是可以的;也许为另一个集合建立交叉索引是个不错的主意,因为在某些情况下它并不适用。它并不适用于所有情况。顺便说一句,我刚刚修复了一个我睡觉后发现的错误。干杯:我不明白将不同的集合作为模板参数传递给flat_map会有什么帮助。没有人这么说。我想你可能还没有完全阅读答案,所以我鼓励你这样做,明天早上我会看到你的评论。晚安您说过:将存储容器参数设置为flat_map比基于具有模板化find membe的排序向量编写字典更好
R我没有完全阅读的是什么?我认为使用string_视图作为键类型是一个非常糟糕的主意,因为它不拥有存储。不过,如果你能控制事物的添加方式,有限的曝光是可以的;也许为另一个集合建立交叉索引是个不错的主意,因为在某些情况下它并不适用。它并不适用于所有情况。顺便说一句,我刚刚修复了一个我睡觉后发现的错误。干杯:我不明白将不同的集合作为模板参数传递给flat_map会有什么帮助。没有人这么说。我想你可能还没有完全阅读答案,所以我鼓励你这样做,明天早上我会看到你的评论。晚安您说过:将存储容器参数设置为flat_map比基于具有模板化find成员的排序向量编写字典更好。我没有完全阅读的是什么?
typedef std::pair< std::string, int > element_type;
std::vector< element_type > map;
struct element_order
{
bool operator()(element_type const& left, element_type const& right) const
{
return left.first < right.first;
}
bool operator()(std::string_view const& left, element_type const& right) const
{
return left < right.first;
}
bool operator()(element_type const& left, std::string_view const& right) const
{
return left.first < right;
}
};
auto find_element(std::string_view const& key)
{
auto it = std::lower_bound(map.begin(), map.end(), key, element_order());
if (it != map.end() && it->first == key)
return it;
return map.end();
}
#include <boost/container/flat_map.hpp>
#include <string_view>
int main() {
boost::container::flat_map<std::string_view, int> m {
{ "one", 1 },
{ "two", 2 },
{ "three", 3 },
{ "four", 4 },
};
std::string key = "one";
auto one = m.at(key);
auto range = m.equal_range(key);
auto it = m.find(key);
m[key] = 1;
}
#include <initializer_list>
#include <algorithm>
#include <utility>
#include <stdexcept>
#include <boost/container/small_vector.hpp>
template <typename K, typename V, typename Cmp = std::less<K>, typename Storage = boost::container::small_vector<std::pair<K, V>, 10> >
struct flat_map {
using key_type = K;
using mapped_type = V;
using key_compare = Cmp;
using storage = Storage;
using value_type = typename storage::value_type;
using iterator = typename Storage::iterator;
using const_iterator = typename Storage::const_iterator;
struct value_compare {
key_compare _cmp;
template <typename A, typename B>
bool operator()(A const& a, B const& b) const { return _cmp(access(a), access(b)); }
private:
static auto& access(value_type const& v) { return v.first; }
template <typename Other>
static auto& access(Other const& v) { return v; }
} _cmp;
storage _data;
flat_map(std::initializer_list<value_type> i) : _data(i) {}
iterator begin() { return _data.begin(); }
iterator end() { return _data.end(); }
const_iterator begin() const { return _data.begin(); }
const_iterator end() const { return _data.end(); }
template <typename Key>
mapped_type& operator[](Key&& key) { return find(std::forward<Key>(key))->second; }
template <typename Key>
mapped_type const& operator[](Key&& key) const { return find(std::forward<Key>(key))->second; }
template <typename Key>
iterator find(Key&& key) {
auto r = equal_range(std::forward<Key>(key));
return (r.first == r.second)? end() : r.first;
}
template <typename Key>
const_iterator find(Key&& key) const {
auto r = equal_range(std::forward<Key>(key));
return (r.first == r.second)? end() : r.first;
}
template <typename Key>
mapped_type& at(Key&& key) {
auto r = equal_range(std::forward<Key>(key));
if (r.first == r.second) throw std::out_of_range("key");
return r.first->second;
}
template <typename Key>
mapped_type const& at(Key&& key) const {
auto r = equal_range(std::forward<Key>(key));
if (r.first == r.second) throw std::out_of_range("key");
return r.first->second;
}
template <typename Key>
auto equal_range(Key&& key) { return std::equal_range(begin(), end(), std::forward<Key>(key), _cmp); }
template <typename Key>
auto equal_range(Key&& key) const { return std::equal_range(begin(), end(), std::forward<Key>(key), _cmp); }
};
#include <string_view>
#include <string>
int main() {
flat_map<std::string, int, std::less<> > m {
{ "one", 1 },
{ "two", 2 },
{ "three", 3 },
{ "four", 4 },
};
std::string_view key = "one";
auto one = m.at(key);
auto range = m.equal_range(key);
auto it = m.find(key);
m[key] = 1;
}