Dictionary 容器平面图和std::string\u视图

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作为我的go to associative集合,原因在他们的文档介绍中被引用,最初的事实是它在编译器的std实现之前提供了更新的特性,并且在不同的平台上都是一样的

现在,我想开始使用string_视图来防止复制字符串,当这些字符串从较大输入的子字符串中获取时。string_视图指向较大字符串中的一系列字符,而无需将它们复制到新的std::string实例中

在获取地图时,我回忆起Boost.Container的另一个渐进特性,我过去喜欢的是保形键,在保形键中,您可以使用与存储的键进行正确比较的任何东西,而不是转换为实际的键类型

但现在我在文档中找不到任何关于这一点的提及。从C++14开始,我就知道std::map现在可以做到这一点,但我更愿意将平面映射用于小集合


几年前,如果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;
}