1

I have a class that contains a std::mutex so it is not movable or copiable.

struct MyObject {
  MyObject(std::string s_) : s(s_) {};
  std::mutex lock;
  std::thread worker;
  std::string s;
};

I can easily add this object to this map:

 std::map<int, MyObject> my_map;
 my_map.emplace(std::piecewise_construct, 
                std::forward_as_tuple(5),
                std::forward_as_tuple("string0"));

But I would like to use a std::array to hold several of them like such:

std::map<int, std::array<MyObject, 3>> my_map;

If MyObject is movable, then I can do:

my_map.emplace(4, {MyObject("string0"), MyObject("string1"), MyObject("string2")});

but this doesn't work (as expected) when the MyObject isn't movable. I can't fall back to piecewise construction since the std::array cannot be constructed from a tuple of 3 strings.

 my_map.emplace(std::piecewise_construct, 
                std::forward_as_tuple(4),
                std::forward_as_tuple("string0", "string1", "string2"));

Is there a way to construct a std::array of non-moveable objects in place in the map?

I'm using these questions as a reference. Is there a way to combine the answers?

emplace and unordered_map<?, std::array<?, N>>

How to allocate a non-copyable and non-movable object into std::map?

I've also tried:

std::array<MyObject, 3> list = {
  MyObject("string0"),
  MyObject("string1"),
  MyObject("string2")
};

my_map.emplace(4, std::move(list));

with the idea that the list should be moveable, but this also does not work.

TheBat
  • 1,006
  • 7
  • 25
  • 3
    You can wrap the `std::thread` in a `std::unique_ptr` to make it movable. – super Dec 08 '21 at 06:26
  • 2
    Btw, is the first `Foo` meant to be `MyObject`? – Enlico Dec 08 '21 at 06:26
  • Thanks! I edited the question to fix the naming issue. – TheBat Dec 08 '21 at 06:28
  • 1
    Does this answer your question? [How should I deal with mutexes in movable types in C++?](https://stackoverflow.com/questions/29986208/how-should-i-deal-with-mutexes-in-movable-types-in-c) – kiner_shah Dec 08 '21 at 06:56
  • @kiner_shah I don't ever want to actually move the object that contains the mutex. It will only ever live in the map that contains it. I only need to move it in during construction. – TheBat Dec 08 '21 at 07:03
  • @TheBat, not sure I understand you, but did you go through the link? – kiner_shah Dec 08 '21 at 07:05
  • Also, do look at this link: https://stackoverflow.com/a/14370753/4688321 – kiner_shah Dec 08 '21 at 07:06
  • Yup, and thanks! That link looks like it would help create an object that is truly moveable which also contains a std::mutex. I don't need that, I need to construct a list of my objects in place within the map. The object will never be moved outside of the map. It seems I can delegate the construction of the objects by forwarding tuples in since the std::array adds another layer of constructors. – TheBat Dec 08 '21 at 07:11
  • Does this answer your question? [How to in-place initialize an array?](https://stackoverflow.com/questions/42309444/how-to-in-place-initialize-an-array) – Sergey Kolesnik Dec 08 '21 at 07:18
  • Look into the last paragraph that mentions C++17 guaranteed copy elision – Sergey Kolesnik Dec 08 '21 at 07:18

1 Answers1

1

With custom array, you might do

template <typename T, std::size_t N>
struct MyArray
{
    template <typename... Us>
    MyArray(Us&&... args) : arr{ std::forward<Us>(args)...} {}

    std::array<T, N> arr;
};

void foo()
{
    std::map<int, MyArray<MyObject, 3>> my_map;
    my_map.emplace(std::piecewise_construct,
                   std::forward_as_tuple(4),
                   std::forward_as_tuple(std::string("string0"),
                                         std::string("string1"),
                                         std::string("string2")));
}

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I modified it slightly. Previously I was using: `using MapEntry = std::array;` I was able to swap that out for: `struct MapEntry : std::array { template LeaderMapEntry(Us&&... args) : std::array{ std::forward(args)...} {} };` And it works! – TheBat Dec 08 '21 at 19:10
  • This is actually pretty cool and forwards the arguments exactly like I wanted. Thanks a bunch!! – TheBat Dec 08 '21 at 19:17