26

I have a non-copyable class (i.e. the copy constructor & assignment operator are marked as 'delete'). I would like to keep these in a std::vector.

It is a RAII class so simply storing the pointer or reference to it is not what I am looking for.

My knowledge of the new initialiser lists & move constructors is somewhat limited, is this possible?

Chris Drew
  • 14,926
  • 3
  • 34
  • 54
Lieuwe
  • 1,734
  • 2
  • 27
  • 41

2 Answers2

34

Yes you can have std::vector<NotCopyable> if NotCopyable is movable:

struct NotCopyable
{
    NotCopyable() = default;
    NotCopyable(const NotCopyable&) = delete;
    NotCopyable& operator = (const NotCopyable&) = delete;

    NotCopyable(NotCopyable&&) = default;
    NotCopyable& operator = (NotCopyable&&) = default;
};

int main()
{
    std::vector<NotCopyable> v;
    NotCopyable nc;

    v.push_back(NotCopyable{});
    v.emplace_back();
    v.push_back(std::move(nc));
}

Live example.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • If you want `push_back` to work correctly (offer the strong exception garantie) you have to declare the move(+ move-Assignment) functions as `noexcept`. – Markus Mayer Nov 13 '14 at 11:52
  • @MarkusMayer Not really. If they aren't declared `noexcept` and the class is also copyable, `push_back` will copy to provide the strong exception safety guarantee. But if it's not copyable, then as long as the move functions don't actually throw, you are safe. – T.C. Nov 13 '14 at 22:29
  • Non-copyable non-movable case: https://stackoverflow.com/questions/39770824/c-container-with-non-copyable-non-movable-element-type – Ciro Santilli OurBigBook.com Nov 20 '20 at 21:55
2

As long as the elements are movable then, yes, simply store them in the vector.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Does `push_back()` actually works on such non-copyable but movable object without explicit `std::move`? – JBL Nov 13 '14 at 10:06
  • How? If I do something like vec.push_back(myClass()) or vec.push_back(std::move(my_class())) it still complains that the copy constructor & assignment operator are deleted. – Lieuwe Nov 13 '14 at 10:09
  • 3
    @Lieuwe: It shouldn't. What is "it"? What compiler? – Lightness Races in Orbit Nov 13 '14 at 10:11
  • @Lieuwe In this case, you should rather use `emplace_back()` if you want to create it in the vector rather than storing an already existing entity. – JBL Nov 13 '14 at 10:11
  • 1
    @JBL: If it's a temporary, yeah. But that's going into the realm of "how do I move objects", which is not this question. – Lightness Races in Orbit Nov 13 '14 at 10:11
  • 1
    You should probably expand on this answer a bit in order to avoid downvotes (e.g. how should members be inserted and removed ; are there any other constraints on which vector member functions can be used (e.g. `resize`)) – M.M Nov 13 '14 at 10:29
  • @LRO - it seems my class was in fact not movable as the compiler didn't implicitly declare a move constructor in my case. – Lieuwe Nov 13 '14 at 10:37
  • 1
    @Matt: This is not the place for a blow-by-blow tutorial on how to store objects of movable types in vectors. The OP has C++ books for that. There's no evidence given in the question that he didn't actually tried to simply _do the thing_ so this is as far as I go! Beyond that we enter the territory of certain duplicates. – Lightness Races in Orbit Nov 13 '14 at 10:37
  • 1
    @Lieuwe: So, it's all been a red herring! – Lightness Races in Orbit Nov 13 '14 at 10:38