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! ]