1

Following code compile (MSVC C++ latest) using std::unordered_map but not with the new boost:unordered_flat_map:

#include "boost/unordered/unordered_flat_map.hpp"
#include <unordered_map>
    class Foo
    {
    public:
        Foo() = default;
        explicit Foo(int x) : m_x_(x) {};
    private:
        int m_x_;
        std::mutex mtx;
        
    };
    
    int main(int argc, char** argv)
    {
        boost::unordered_flat_map<int,Foo> map_test; //compile with std::unordered_map
        map_test.try_emplace(1,1);
        return 0;
    }

I dont expect it to work with flat_map as with std::map , guessing as the map need reordering, elements need to be able to move/copy. But I dont get why its working with unordered_map and not boost:unordered_flat_map.

qwark
  • 493
  • 1
  • 4
  • 15
  • 2
    It should work with `boost::unordered_map` but not with `boost::unordered_flat_map`. The latter requires object movement to keep it flat I believe. – ALX23z Jan 07 '23 at 19:46
  • Where is this constraint documented ? Also the compilation error is very cryptic, is there no use of concepts at all ? – qwark Jan 08 '23 at 17:29
  • concepts arrive with C++20. It takes a while before a library can shifts towards using them, especially one as large as boost. Besides, some of the most important features of C++20 haven't yet been properly implemented, so it will be a while before community begins to use it, aside from some small projects. – ALX23z Jan 08 '23 at 21:35

1 Answers1

1

The leading factor is not whether the container uses ordered storage organization. It's not as if the collection is reordered (because key properties are immutable, the comparator is fixed and needs to be referentially transparent /idempotent).

Node Based vs. Flat Containers

Instead, the leading factor is how struggle is allocated. Flat maps are called flat because they allocated their elements into a flat region, like a vector. This causes reallocation when the container grows.

In short, move is required on reallocation. By contrast, both std::map and std:: unordered_map are node-based containers, i.e. they perform allocation per element (wrapped in nodes that may contain extra metadata).

In node based containers elements don't need to be moved even if their relation inside the container chances. This is also what gives nude based containers their reference/iterator stability characteristics.

Ordering Invariants

In addition to reallocation, flat containers may need to move elements on insertion/removal to maintain the ordering invariant.

You figured this part, but the inverse doesn't hold because of the reallocation requirements.

sehe
  • 374,641
  • 47
  • 450
  • 633