On 2016-02-20 1:11 AM, Steven Watanabe wrote:
AMDG
On 02/19/2016 07:48 PM, Phil Bouchard wrote:
On 2016-02-19 9:30 PM, Steven Watanabe wrote:
On 02/19/2016 05:53 PM, Phil Bouchard wrote:
On 2016-02-18 11:53 PM, Phil Bouchard wrote:
I have to admit MSVC 2015 got a clean STL...
Their STL is good but unfortunately they pass their pointer arguments by value and not by reference so it makes it impossible to use smart pointers for internal node pointers.
I don't understand how pass-by-value would break smart pointers. I can see that it might be inefficient, but it shouldn't actually fail.
Because the only way to deallocate the content of a smart pointer is by deallocating and resetting its pointer to 0, which modifies the pointer.
For example:
1) The allocator's deallocate function will call p.reset():
<snip> 2) In MSVC 2015 the deallocate function is called by this one which has a pointer passed by value:
template<class _Alloc> struct _Wrap_alloc : public _Alloc { // defines traits for allocators [...] void deallocate(pointer _Ptr, size_type _Count) { // deallocate object at _Ptr, ignore size _Mybase::deallocate(_Ptr, _Count); }
That isn't specific to MSVC: [allocator.requirements]:
Table 27: "p a value of type XX::pointer, obtained by calling a1.allocate, where a1 == a
Table 28: "a.deallocate(p,n)"
p is not required to be an lvalue, here.
[allocator.members]: "void deallocate(pointer p, size_type n);"
(C++11)
3) Which in turn is called by another one using a parameter passed by value:
template<class _Alloc_types> class _List_alloc { // base class for list to hold allocator public: [...] void _Freeheadnode(_Nodeptr _Pnode) { // free head node using current allocator _Getal().destroy( _STD addressof(_Nextnode(_Pnode))); _Getal().destroy( _STD addressof(_Prevnode(_Pnode))); _Getal().deallocate(_Pnode, 1); }
4) ...
The bottom line is resetting a copy of a smart pointer won't do anything. This is why it needs to be passed by reference.
You can't deallocate anything, anyway, because there may be other copies of the pointer. The whole point of using smart pointers in the first place, is that the deallocate is run automatically. Just leave allocator.deallocate as a no-op and let the memory be freed when the pointer is destroyed or assigned.
I think you're right, thanks for the hint!