Has C++11 changed requirements for elements of STL containers, and how?
Asked Answered
L

1

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...

Lizzielizzy answered 27/11, 2012 at 5:25 Comment(3)
I believe C++11 requires a copy constructor or a move constructor (similarly, copy assignment or move assignment).Anechoic
"Has C++11 changed requirements for elements of STL containers?" Yes, very much so. Have you read even obvious places e.g. Wikipedia before asking?Passage
@Passage okay then, I edited my question so that my intention is clearly expressed.Lizzielizzy
G
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.

Gelatinous answered 27/11, 2012 at 6:13 Comment(5)
What do you refer to when you need to know requirements of specific operations? Anyone who read this page will be benefited.Lizzielizzy
@NicolBoras: Oh, that requires reading of the standard... I'll grab one. Thank you!Lizzielizzy
vector::emplace_back still requires that the elements be moveable/copyable, since it may grow the vector.Unicycle
@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.Calandra
@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.Gelatinous

© 2022 - 2024 — McMap. All rights reserved.