Every piece of knowledge must have a single, unambiguous, authoritative representation within a system
Andy Hunt and Dave Thomas, The Pragmatic Programmer
vector<int> and vector<string> is the same (implementation sameness)handle_disturbance() could be thought of as part of the non-intrusive interface of vector<unique_ptr<Animal>>handle_disturbance() is not part of the interface of vector<int>/* ... */?/* ... */ is something like...OfThings in C++?Barnyard and CanvasOwningCollection is typically called a mixinOwningCollection<Animal> is unrelated to OwningCollection<Shape>ComparableElementwise uses curiously recurring template pattern (CRTP)elements() member function is sometimes called a customization pointelements() can be used to express multiple unrelated types of "sameness"thisoperator<=> is a language-level mixin for comparisonsT&& is called a "forwarding reference" (or sometimes, a "universal reference")this to the rescue!vector directly to the user?Every piece of knowledge must have a single, unambiguous, authoritative representation within a system
Andy Hunt and Dave Thomas, The Pragmatic Programmer
Owning and the Collection parts!Owner be?shared_ptrstd::vector<T, Allocator=std::allocator<T>>std::queue<T, Container=std::deque<T>>std::queue<T, Container=std::deque<T, std::allocator<T>>>std::unique_ptr<T, Deleter=std::default_delete<T>>separable from how that memory (and even the object itself!) is created or destroyedunique_ptrstd::unique_ptr<T, Deleter=std::default_delete<T>>unique_ptr<T, Deleter>::pointer is (basically) Deleter::pointer if that type exists, otherwise T*.boost::offset_ptrEvery piece of knowledge must have a single, unambiguous, authoritative representation within a system
Andy Hunt and Dave Thomas, The Pragmatic Programmer
unique_ptrshared_ptr!std::string, std::vector, [...], to shared_ptr, does so through an Allocator."unique_ptr and shared_ptr: 🤦🏼♀️ 🤦🏼♀️ 🤦🏼♀️unique_ptr<T, Deleter> is "broken," right?shared_ptr uses allocators, so...d(ptr)alloc.destroy(ptr) then alloc.deallocate(ptr, 1)allocate_shared to the rescue?allocate_sharedshared_ptr constructors, allocate_shared does not accept a separate custom deleter: the supplied allocator is used for destruction of the control block and the T object, and for deallocation of their shared memory block."make_shared when no allocation or deletion customization is needed,allocate_shared when we need to customize either of those…
allocate_unique's complexity would result from the fact that the Standard Library currently doesn't contain enough machinery to implement it—specifically, to adapt allocator syntax to deleter syntax. (Returningunique_ptr<T, unspecified>would be inconvenient for users.) This is unlikeallocate_shared, becauseshared_ptris powered by type erasure.
Stephan T. Lavavej, N3588
While this proposal doesn't provide
allocate_unique(and is recommending that it never be provided), one way to provide it without introducing a wrapper class could be to unify deleters and allocators inunique_ptr's specification. That is, specifying that if the expressiond(ptr)is not valid, thenDshall meet theAllocatorrequirements.
Stephan T. Lavavej, N3588
unique_ptr rabbit hole)constexpr functions