Boost logo

Boost :

From: Reece Dunn (msclrhd_at_[hidden])
Date: 2004-05-20 17:47:56


Rob Stewart wrote:
>From: "Reece Dunn" <msclrhd_at_[hidden]>
> >
> > Currently, this implementation is missing iterator support (and thus all
> > basic_string functionality that relies on begin(), end(), etc). This is
> > because I am wondering how to map them from the basic_string adaptor to
>the
> > implementation (knowing that you cannot have const and non-const virtual
> > functions).
>
>Since when can you not have const and non-const virtual
>functions?

Let me rephrase:

   class char_string
   {
      virtual iterator begin() = 0;
      virtual const_iterator begin() = 0; // oops! begin already in vtable!!
   };

> > I have two possible solutions:
> > [1] name the const versions cXXX (cbegin(), crend(), etc.) -- the
>problem
> > with this is that you have 8 virtual functions!

I was meaning to modify the above to:

   class char_string
   {
      virtual iterator begin() = 0;
      virtual const_iterator cbegin() = 0; // ok - cXXX variant
   };

>You'd have those same eight variations with const and non-const
>virtual functions.

That's the problem -- too many virtual functions.

> > [2] direct to non-const versions and convert to const iterators:
> > inline const_iterator begin() const
> > {
> > return( const_iterator( const_cast< basic_string_impl & >( *this
> > ).begin()));
> > }
> > but I am debating whether this is standards compliant and if it is a
>good
> > design decision.
>
>If the object is really const, then this results in undefined
>behavior.

I have disregarded this idea.

> > If there are alternate solutions, I'd like to hear them.
>
>Use const and non-const virtual functions. ;-)
>
> > Another possibility would be to construct the iterators from offsets:
> >
> > inline iterator begin()
> > {
> > return( get_impl().iter_offset( 0 ));
> > }
> > inline reverse_iterator rbegin()
> > {
> > return( reverse_iterator( get_impl().iter_offset( size() - 1 )));
> > }
> >
> > That way you would only need two functions (iter_offset and
> > const_iter_offset).
>
>But how would the iterator know whether to give const or
>non-const access to the elements?

iter_offset = non-const access (e.g. begin())
const_iter_offset = const access (e.g. rend() const)

   class char_string
   {
      virtual iterator iter_offset( difference_type ) = 0;
      virtual const_iterator const_iter_offset( difference_type ) = 0;
   };

   template< class Derived, ... > class basic_string_impl >
   { public:
      inline iterator begin(){ return( get_impl().iter_offset( 0 )); }
      inline const_iterator begin() const{ return(
get_impl().const_iter_offset( 0 )); }
   };

NOTE: it is not necessary for Derived to be implemented with virtual
functions, but each function name is unique so if they are virtual there
isn't a problem.

I have tested this on VC6, VC7, VC71 and BCB and it works :).

Regards,
Reece

_________________________________________________________________
Stay in touch with absent friends - get MSN Messenger
http://www.msn.co.uk/messenger


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