Re: setter for deleter in boost::shared_ptr (and alike)
 
* Alberto Ganesh Barbati:
Alf P. Steinbach ha scritto:
For
example, the operation to replace or change (whatever) the deleter could
require the deleter to be of class type convertible to
"replacable_deleter", in which case the instantiating code would still
have full control, but now a by default locked door.  Or, less draconian
and perhaps more practical, security-by-obscurity, the operation to
unlock could require supplying an object implementing "replace_deleter",
which could be made not-completely-trivial to implement, so that other
code wouldn't do that by accident, some spur of the moment idea.
The same effect can be achieved in a very much simple way by just having
get_deleter() return a const pointer. In that way, if the user wants to
modify the deleter he/she must either rely on mutable members or use a
const_cast. Both are ugly enough to say they won't be used by accident.
I didn't think of that.
It's funny how obvious something can be with hindsight, when someone
else (here you) points it out.
So yes I agree, that's a good solution, in the sense of minimizing the
change from the current definition while fixing the worst problems, but
I think it requires wording to the effect that the deleter is not stored
as const (just for the formal effect of const_cast).
In this case there is no information stored in the deleter, but it's not
hard to imagine a case where it might be useful to do so. For example,
suppose you have a naive heap-based memory management:
class heap
{
   ...
   template <class T>
   struct delete_from_heap
   {
     heap* m_h;
     delete_from_heap(heap* h) : m_h(h)
     {}
     void operator()(T* ptr) const
     {
       ptr->~T();
       m_h->deallocate_raw_memory(ptr);
     }
   };
public:
   template <class T, class... Args>
   shared_ptr<T> allocate(Args&&... args)
   {
     void* ptr = allocate_raw_memory(sizeof(T));
     ::new(ptr) T(std::forward<Args>(args)...)
     return shared_ptr<T>(ptr, delete_from_heap<T>(this));
   }
};
Now, suppose you already have an object allocated in such way and you
want a method to allocate a new object *on the same heap* (because you
are concerned with locality, for example). This could be achieved like
this:
   template <class T, class U, class... Args>
   static
   shared_ptr<T> allocate_same_heap(shared_ptr<U> ptr, Args&&... args)
   {
     // might as well be const delete_from_heap* here
     if (delete_from_heap* del = get_deleter<delete_from_heap>(ptr))
     {
       return del->m_h->allocate<T>(std::forward<Args>(args)...)
     }
     else
     {
       // not allocated from a heap
       throw /* something here */;
     }
   }
Do you see a problem in having this kind of access?
Uhm, that delete_from_heap isn't accessible in allocate_same_heap? <g>
Of course you mean the get_deleter function.  I've discussed that
else-thread.  IMHO it needlessly invites Undefined Behavior by the
possibility of returning a nullpointer (that may be dereferenced by
careless client code), but I gather that for many that little risk is
outweighted by what's perceived as a notational advantage, and since
get_deleter is established, even though not much used, changing the
interface could break code: it could break code made between now and
C++0x, as use of shared_ptr becomes more common.
Regarding having this /access/, I think it's mostly fine.  But the
example illustrates that given that access one may want to propagate all
kinds of associated information via the deleter, which thus may evolve
into a large beast that's possibly not even a deleter except for the
necessity to handle also that task in order to serve as carrier.  On the
third hand, trying to solve that potential problem, shared_ptr could
become a case of featuritis: as it is, it's minimal and simple, and I
would much rather see functionality to transfer raw pointer + deleter to
arbitrary other smart pointer, than support for associated information.
Cheers,
- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]