Boost logo

Boost :

From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2002-04-19 15:26:43


"Gennadiy Rozental" <rogeeff_at_[hidden]> wrote in message
news:a9pp8u$4gp$1_at_main.gmane.org...
>
> "Fernando Cacciola" <fcacciola_at_[hidden]> wrote in message
> news:a9pnih$1jm$1_at_main.gmane.org...
> >
> > "Gennadiy Rozental" <rogeeff_at_[hidden]> wrote in message
> > news:a9pjah$oog$1_at_main.gmane.org...
> > >
> > > "Fernando Cacciola" <fcacciola_at_[hidden]> wrote in message
> > > news:a9pfv7$cb7$1_at_main.gmane.org...
> > > > Just my 2 cents...
> > > >
> > >
>
> [...]
>
> > > >
> > > > template<class APtr>
> > > > class Processor
> > > > {
> > > > Processor ( APtr const& obj ) : m_obj(obj) {}
> > > > ...
> > > > APtr m_obj ;
> > > > } ;
> > > >
> > > > These, however, intoduces a much higher engineering complexity to
the
> > > > system, because we have changed a non-template class to a template
> class
> > > > only because the smart_ptr is overparametrized (from the pov of the
> user
> > > of
> > > > A who just wants to keep it alive).
> > >
> > > No. I disagree. Real problem here you want to reuse you Processor
> > facility,
> > > but do not know storage type. There as usual two choises runtime
> > > polimorphizm - which I hardly believe you can accept, or compile-time
> one
> > > with we usually express in form of template parameters. And FWIW it
does
> > not
> > > "intoduces a much higher engineering complexity".
> > >
> > But it does. Remember that Processor IS NOT A TEMPLATE class, and turing
a
> > non-template class into a template class *is* a very complex enginnering
> > change. For the simplest of the reasons, if you change the implemention
of
> a
> > template class you need to recompile the world because exporting
templates
> > is not currently available.
>
> Do you know compile-time based solution that does not have this issue?
>
Solution to what?
In this case, the 'problem' for which I will need a compile-time solution is
introduced by an intrusive-policy smart ptr, because such policies are part
of the interface (see below). I just don't have a problem to solve if I used
a smart ptr which uses policies under the hood, so I don't need a
compile-time 'solution' (I don't need to make Processor a template class).

> >
> >
> > > >
> > > > Scenario 2:
> > > >
> > > > It is quite common to specialize certain things -such as predicates-
> on
> > a
> > > > smart_ptr<>. This is in order to allow certain expressions to be
> applied
> > > > indistinctely to bare and smart pointers.
> > > > For example, the boost shared-ptr declares:
> > > >
> > > > // get_pointer() enables boost::mem_fn to recognize shared_ptr
> > > > template<typename T> inline T * get_pointer(shared_ptr<T> const & p)
;
> > > >
> > > > This is used -as the comment says- inside mem_fn which allows a very
> > > > powerful usage of mem_fn.
> > > >
> > > > If shared_ptr were intrusively policy-based, this wouldn't be
feasible
> > > > becuase mem_fn couldn't know about the smart pointer policies.
> > >
> > > Why? Can't you write another predicate like this:
> > >
> > > template<typename StoragePolicy,...> inline
StoragePolicy::pointer_type
> > > get_pointer(smart_ptr<....> const & p) ;
> > >
> > mem_fn doesn't know about the different policies introduced in the
> complete
> > type it sees. So this would only work as long as there is one
get_pointer
> > specialization for each of the possible policy combinations.
>
> Why? Here now mem_fn is using get_pointer:
> template<class U> R const & call(U & u, void const *) const
> {
> return (get_pointer(u)->*f_);
> }
>
> Given my definition of get_pointer for smart_ptr. It does not need to know
> anything about policies of smart_ptr. So the same as with current
> shared_ptr we need to write get_pointer once.
>
The implementation of mem_fn is irrelevant... is the implementation of the
get_pointer specialization which matters.
I can write the specialization of smart pointer only once because it is a
template with only one parameter.
How would you write the specializations for get_pointer<> for SmartPtr? The
specializations must work with bare pointers and third-party conventional
smart pointers as well, as it does now.

>
> > > > Dietmar already shown -and I totally agree- that most of the smart
ptr
> > > > policies are usually type dependent, so they perfectly call for
> external
> > > > policies. (BTW, the sketch made by Doug seems very reasonable).
> > >
> > > I disagree here. What is type dependent? Specifically?
> > >
> > The count strategy (intrusive (either COM based or else) or external)
>
> See my other post regarding all possible Ownership strategies for the same
> type T
>
I didn't mentioned an ownership strategy. The fact that a given object -if
shared- should use an intrusive or external refcount is orthogonal to the
choice of sharing or exclusively-owning the object.

> > The deallocation strategy is most of the times type-dependent.
>
> This is also is not obvios. In some case I want delete pointrs of type T,
in
> other cases want to return them in some pool. Or do one or the othe
depends
> on some logic.
>
Yes, but these should be categorized as the unusual cases. I dare to state
that more than 90% of the time pointers are deallocated with delete, FILE*
with fclose, handles with type-specific API calls, etc...

> > These, along with the threading policy, are IMO the three most practical
> > strategic choices for a *general* smart pointer.
>
> How could you choose proper threading policy by given type T?
>
I don't know...

> > And again... we are not against policy-based designs.. we are just
trying
> to
> > figure out different ways to specify the policies; in search of one that
> > doesn't clutter the interface that a user would like to use.
>
> And again, I do not concider Polcies Names part of the interface, but
rather
> part of class name, fixed in any given application of the framework.
>
How do you consider the 'class name' not part of the interface?

If you have either smart_ptr<T,X> or smart_ptr<T,Y> or smart_ptr<T,Z>....
how do you think X,Y and Z are part of the interface?
What do you understand as being the interface?

It seems to me that you are baseing your argument in the assumption that
smart pointers are used through a typedef, as in:

typedef smart_ptr<MyClass,Policy1,Policy2,Policy3> MyClassPtr ;

But this is not the case in many practices.

If we had template typedefs, then our whole argument would be wrong... but
that feature is not available.

--
Fernando Cacciola
Sierra s.r.l.
fcacciola_at_[hidden]
www.gosierra.com

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