4

This is essentially a follow up to my earlier question Difference between std::unordered_map < K, boost::ptr_deque < T > >'s operator[] (K const &) and emplace

I am trying to implement a associative vector (call it unordered_flat_map) and would like to support operator [key]

Here is the code...

#include <utility>
#include <tuple>
#include <vector>

struct T
{
    T() = default;
    T(T const &) = delete;
    T & operator = (T const &) = delete;
    T(T &&) = delete;
    T & operator = (T &&) = delete;
};

using S = T;

int main()
{
    using value_type = std::pair < uint32_t, S >;
    std::vector < value_type > testuvm;
    value_type p(std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple());
    //  testuvm.emplace_back(std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple());
}

The commented out line fails to compile, which is what unordered_map::operator [] does if the key is not found. Is there a way to make this work? If not, why is this not possible? Is this due to a limitation of vector?

Community
  • 1
  • 1
zrb
  • 851
  • 7
  • 16

1 Answers1

8

In documentation of std::vector::emplace_back, note the requirement for the type to be MoveInsertable.

While emplace_back does not move the new element, it might still need to move the existing elements when it reallocates the storage. So there is no practical way to use a vector with immovable type.

Note that std::deque::emplace_back does not have that requirement and should be, with some care, usable.

Or, if you need to use vector, you can wrap the type in std::unique_ptr to make it movable.

Andre Holzner
  • 18,333
  • 6
  • 54
  • 63
Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • Thanks. But this is a very specific use case where I need it to be a `vector` – zrb Sep 05 '16 at 07:41
  • 1
    @zrb, if it has to be a `vector`, then you'll have to make the type movable. By wrapping it in a `std::unique_ptr` if nothing else helps. – Jan Hudec Sep 05 '16 at 10:23