Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-06-13 08:22:51


> I looked over the smart pointers at boost.org, and I was
> surprised not to find a pointer defined to give value-semantic
> behavior to polymorphic types.
> I have been using such a pointer for a while now in my code,
> and I have found it to great use.

Indeed, there are situations when something like this is _very_ helpful. My
favorite example is 'any_iterator<>' class template, which is basically
something like 'boost::any' in application to iterators :). Although 'any'
itself would benefit from using a cloning pointer, as now it implements all
the boilerplate operations (zero initialization, checking for 0 before
cloning, deletion in destructor, swap-based assignment) "manually", case
with 'any_iterator<>' is IMO even more interesting (but harder to describe
shortly :). As with "traditional" iterators, there should be two versions of
'any_iterator<>' - const and non-const, and it should be possible to
(effectively) convert non-const into const ones. Clearly, having two
different templates, let's say 'any_iterator<>' and 'any_const_iterator<>',
and defining a converting constructor from the first to the second one is
not a very attractive option, because of quite an amount of duplicated code.
Another option is to introduce a convention that 'any_iterator<int>' is a
"plain" one and 'any_iterator<int const>' is a const one, and then use the
Matt's (or Jeremy's?) technique -
http://www.cuj.com/experts/1901/austern.htm?topic=experts - to implement the
rest; and here the interesting part begins. In essence, the resulting code
could look like this:

template<typename T, class Category, bool IsConst =
boost::is_const<T>::value>
struct any_iterator
    : std::iterator<Category, typename boost::remove_const<T>::type >
    {
    // copy constructor OR converting constructor, depending on T
    any_iterator(any_iterator<T, IteratorCategory, false> const& other)
        : itor_holder(other.itor_holder->clone())
        {
        }
    // ...
    private:
        iterator_placeholder<T, IteratorCategory>* itor_holder;
    };

Looks good, isn't it? :). The only problem here is that in case when the
constructor above is a converting one, then we still need to implement an
ordinary copy constructor, because the implicitly generated one will do a
wrong thing... and we cannot define a copy constructor because when, in case
of non-const T, there will be two of them.. the technique cannot be applied
until you make sure that you can safely delegate a job of defining a copy
constructor to the compiler (e.g. using a cloning pointer). Lesson?
Sometimes using plain pointer instead of smart one not only requires more
typing and is more error-prone, it can also prevent you from implementing
really cool designs :).

> Is there a reason why such a pointer has not been included in
> the libraries?

There've been a few proposals, but they never got to the point of formal
review.

Aleksey


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