|
Boost : |
From: Greg Colvin (gcolvin_at_[hidden])
Date: 2001-09-03 13:45:43
From: Peter Dimov <pdimov_at_[hidden]>
> > From: "Peter Dimov" <pdimov_at_[hidden]>
> > > There is a break-even point past which a custom smart pointer constructed by
> > > defining the appropriate policies becomes harder to write, more error prone,
> > > less readable and less efficient compared to simply implementing the class
> > > from scratch. And coming up with a good policy-based design (one with a
> > > reasonable break-even point) is difficult.
> >
> > I think we learned some things from the iterator adaptor library, which
> > AFAICT has been a success. I'm not sure we can apply all of those lessons,
> > but it may yet be possible. The first thing missing is a Pointer Concept
> > family definition along the lines of the Iterator Concept family.
>
> Leading C++ experts can't agree on a common informal definition of the term
> "smart pointer" (the best they can think of is "anything that redefines *
> and ->") and you think that we can devise a Pointer Concept? ;-)
Sure we can. But not THE Pointer Concept. Humpty Dumpty was closer
to right in the world of programming than in the real world.
> Although my point was more along the lines that even given a policy-based
> smart pointer, your particular case would most probably still call for an
> old school, hand written implementation.
Warning: never-tested, never-compiled code off the top of my head,
based on various experiments over the years, including Peter Dimov's
most recent refactorization.
It seems that by adding one constructor to shared_ptr and shared_array
we could satisfy Dave's needs:
shared_ptr::shared_ptr(
T* object, shared_counter_base* counter=shared_ptr_counter);
shared_array:shared_array(
T* array, shared_counter_base* counter=shared_array_counter);
Where shared_counter_base is something like:
class shared_counter_base {
protected:
long count;
void* object;
void (*destroy)(void*);
public:
shared_counter_base(): count(0),object(0),destroy(0) {}
void increment() { ++count; }
void decrement() {
if (!--count)
assert(destroy), destroy(object);
}
};
It is the job of the destroy function to release storage for the
shared object and itself when the count goes to zero. I use a
pointer-function rather than a virtual destructor so as safe a
smidgen of time and so as not to forclose options for how the
counter is allocated.
Then Dave can derive his own counter class and arrange for his array
allocator to stash the counter at the head of his array.
Whether this is easier to do than to write his own class I can't say.
It would be a slightly larger header than needed for a custom
implementation. One advantage to this approach, if it matters, is
that the rest of Dave's code can traffic in shared_array without
caring about the array allocator.
And for those who have not been "Through the Looking Glass":
"When _I_ use a word," Humpty Dumpty said in rather a scornful
tone, "it means just what I choose it to mean -- neither more
nor less."
"The question is," said Alice, "whether you CAN make words mean
so many different things.'"
"The question is," said Humpty Dumpty, "which is to be master --
that's all."
But then Humpty Dumpty had a great fall.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk