27

Recently I'm surprised at the fact std::unique_ptr is acceptable for elements of STL containers, because I thought these elements are required to provide functions below(this page says the same):

  • public default constructor with no arguments
  • public copy constructor
  • public copy assignment operator function
  • public destructor

But std::unique_ptr is not copyable to make the pointer it holds owned by a single object, that contradicts the requirements above.

Has the standard changed the requirements? If so, what are the changes? Perhaps either movable objects or copyable ones are sufficient? I've searched the web whether the requirements has changed since C++11, but I can't find any page which helps me...

Community
  • 1
  • 1
k2_8191
  • 407
  • 1
  • 5
  • 10
  • 4
    I believe C++11 requires a copy constructor *or a move constructor* (similarly, copy assignment or move assignment). – Lily Ballard Nov 27 '12 at 05:26
  • "*Has C++11 changed requirements for elements of STL containers?*" Yes, very much so. Have you read even obvious places e.g. [Wikipedia](http://en.wikipedia.org/wiki/C%2B%2B11) before asking? – ildjarn Nov 27 '12 at 05:38
  • @ildjarn okay then, I edited my question so that my intention is clearly expressed. – k2_8191 Nov 27 '12 at 05:54

1 Answers1

24

Yes, there have been major changes to the requirements for standard library containers. It's hard to provide a comprehensive list (there were a lot), but here are some important ones:

std::vector generally requires only that its members be MoveConstructible and MoveAssignable. There are many member functions of std::vector that impose more strict requirements. vector::push_back requires Move or CopyConstructible (depending on whether you pass an rvalue or lvalue), but the new vector::emplace_back only requires that there is an accessible constructor that takes the given parameters (in addition to the baseline requirement). Obviously any attempt to invoke the vector's copy constructor/assignment will require that the type be CopyConstructible (ie: you can't copy a std::vector<unique_ptr>).

Similarly, most other containers have reduced the restrictions on the type. They also have emplace member functions that allow you to construct the members in-place, as well as l/rvalue insertion functions. Which means that you don't have to copy values in; you can move them in or construct them in-place.

None of the constructors or destructors are required to be public; all construction takes place via calls to allocator_traits<Allocator>::construct calls. So if you provide an allocator, you could make your constructors/destructors private. Well, as long as your allocator class can access them, of course.

In short, the requirements are much less strict, but they're a bit more complex. You can get away with a lot of things if you restrict yourself from performing certain operations on the container.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • What do you refer to when you need to know requirements of specific operations? Anyone who read this page will be benefited. – k2_8191 Nov 27 '12 at 06:47
  • @NicolBoras: Oh, that requires reading of the standard... I'll grab one. Thank you! – k2_8191 Nov 27 '12 at 07:05
  • 3
    vector::emplace_back still requires that the elements be moveable/copyable, since it may grow the vector. – Nevin Nov 27 '12 at 07:50
  • 2
    @Nevin: yes, more specifically, since it cannot be statically eliminated that `emplace_back` may grow the vector, even if the capacity is sufficient it is deemed necessary that the elements can be either copied or moved. – Matthieu M. Nov 27 '12 at 08:02
  • @Nevin: As I said, "*There are many member functions of std::vector that have more strict requirements.*" Followed by listing some of those more strict requirements. All of those requirements are *in addition to* the move requirement. – Nicol Bolas Nov 27 '12 at 08:05