Boost logo

Boost :

Subject: Re: [boost] [Container] Inner Smart Pointers
From: Phil Bouchard (phil_at_[hidden])
Date: 2016-02-19 21:48:43


On 2016-02-19 9:30 PM, Steven Watanabe wrote:
> AMDG
>
> 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():

template <typename T, typename UserPool = system_pool<system_pool_tag,
sizeof(char)> >
     class block_allocator
     {
         typedef T element_type;

     public:
         typedef element_type value_type;
         typedef size_t size_type;
         typedef ptrdiff_t difference_type;
         typedef block_ptr<element_type> pointer;
         typedef block_ptr<const element_type> const_pointer;
         typedef element_type & reference;
         typedef const element_type & const_reference;

        [...]

         pointer allocate(size_type s, const void * = 0)
         {
             return new block<value_type, UserPool>();
         }

         void construct(pointer & p, const T & x)
         {
         }

         void destroy(pointer & p)
         {
         }

         void deallocate(pointer & p, size_type)
         {
             p.reset();
         }
     };

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);
                }

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.

-Phil


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk