|
Boost : |
From: David B. Held (dheld_at_[hidden])
Date: 2002-04-30 18:20:06
"Greg Colvin" <greg_at_[hidden]> wrote in message
news:5.1.0.14.0.20020430122950.02e48ce0_at_GMMAIL...
> [...]
> The client of a shared_ptr need not be concerned with where
> the reference count is stored, how the referenced object is
> destroyed, or how the memory for the count and object is
> managed, so why should those details get exposed in the name
> of the smart pointer type?
Well, my understanding is that while those details don't make a whit
of difference as to how the pointer is *used*, it does make a
difference as to how the pointer can interoperate with other pointers
that have different implementations. Does it just come down to
writing conversions to shared_ptr and back?
> Using shared_ptr those details are set when the smart pointer
> is constructed, and need not be revealed to the client. Note that
> this means that the creator of a smart pointer can change those
> details without requiring recompilation of its clients, and without
> breaking binary compatibility.
So are you suggesting that I, as a clever user of shared_ptr, could
have one set of "stock" boost::shared_ptr<T>s in one part of my
app, and a different set of boost::shared_ptr<T>s in a different
part of my app, where I re-implement shared_ptr to use, say,
COM ref-counting? Does this violate ODR? Or would I have
to give my version of shared_ptr a different name? Or is it the
case that I can only have one implementation of shared_ptr in a
given app, but it doesn't have to be the "normal" one? I'm really
unclear on the "changing the details" part.
> I don't see why a policy-based smart pointer template cannot
> preserve this feature of shared_ptr.
My understanding is that shared_ptr fixes the Checking policy,
Conversion policy, and Ownership policy to AssertCheck,
DisallowConversion, and external ref-counting. While it is able
to use an intrusive refcount, it only works with one kind of intrusive
count, and to use this count, it must be initialized from a pointer
with a different type name. boost::smart_ptr still divides up
functionality among type names. It just does so with explicit
names, instead of templated names. boost::scoped_ptr is to
boost::shared_ptr as Loki::SmartPtr<DestructiveCopy> is to
Loki::SmartPtr. And you could even typedef the SmartPtrs to
look just like their boost equivalents, no? As far as interoperability
among Ownership types, that's just a matter of writing the
appropriate policies. It should be trivial to write a
BoostRefCounted ownership policy that uses the boost::counted_base
count, provides construction from boost::shared_ptr and
boost::intrusive_ptr, as well as to Loki::SmartPtr<BoostIntrusive>.
Here's a rough outline, with extraneous details removed. It should
demonstrate that it is entirely possible to create a
Loki::SmartPtr<BoostRefCounted> that interoperates with
Loki::SmartPtr<BoostIntrusive> just like boost::shared_ptr<>
interoperates with boost::intrusive_ptr<>.
template <typename P>
class boost_ref_counted
{
private:
// Borland 5.5.1 specific workarounds
typedef checked_deleter<T> deleter;
typedef shared_ptr<T> this_type;
public:
ref_counted()
: count_(0, deleter())
{
}
boost_ref_counted(const boost_intrusive<P>& p)
: count_(p.get())
{
}
P clone(const P& val)
{
count_.add_ref();
return val;
}
bool release(const P&)
{
// shared_count does the deleting
return false;
}
void swap(ref_counted& rhs)
{
count_.swap(rhs.count_);
}
private:
// Data
detail::shared_count count_;
};
After writing the code, I realized that making Loki::SmartPtr interoperate
with boost::shared_ptr would require cooperation with shared_ptr. But
there is certainly nothing in principle from preventing this.
Dave
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk