How to deal with noncopyable objects when inserting to containers in C++

Viewed 10144

I'm looking for the best-practice of dealing with non-copyable objects.

I have a mutex class, that obviously should not be copyable. I added a private copy constructor to enforce that.

That broke the code - some places simply needed to be fixed, but I have a generic problem where a class, using the mutex either as a data member, or by inheritance, is being inserted into a container.

This is usually happening during the container initialization, so the mutex is not initialized yet, and is therefore ok, but without a copy constructor it does not work. Changing the containers to contain pointers is not acceptable.

Any advise?

10 Answers

std::vector can not store non-copyable objects (due to resize) thus you can't store objects of type Foo:

struct Foo {
   std::mutex mutex;
   ...
};

One way around this is to use std::unique_ptr:

struct Foo {
   std::unique_ptr<std::mutex> pmutex;
   Foo() : pmutex{std::make_unique<std::mutex>()} {}
   ...
};

Another option is to use a std::deque which can hold non-copyable objects (like instances of the first version of Foo above. Typically use emplace_back method to construct objects "in place" to add elements -- no copies happen. For example, objects of type Foo here do not need to be copiable:

struct FooPool {
    std::deque<Foo> objects;
    ObjectPool(std::initializer_list<T> argList) {
        for (auto&& arg : argList)
             objects.emplace_back(arg);
    ...
};
  
Related