Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-02-27 05:53:50


Dave Abrahams wrote:
> In nearly all the examples we could think of, the amount of
> typing needed to
> actually use iterator_adaptor was considerably reduced. Can
> you give an
> example that shows how things have become worse?

May be that's only me, but IMO the amount of typing is not the most
important thing when you are dealing with a complex template code like one
of iterator adaptors' library. Some people have real difficulties with
remembering an order of template parameters if there are more than 3 of them
(<g> :), but seriously, every time I use such template I have to look at its
definition to check if I got it right), and given that often providing the
template arguments in a wrong order is not immediately followed up by a
proper diagnostics (and concepts checking doesn't help here as much as
wanted), I think it's reasonable to assume that one would prefer to type a
little bit more and be sure that he/she got it right from the first time. Of
course, simple replacing of 5 template parameters by a traits type with the
same 5 parameters wouldn't help, but factoring out the typedefs-only part of
the original class template allows to apply so-called 'named template
parameters' technique which can simplify things *a lot*, at least for people
like me :).

To illustrate the technique, here is the original code snippet from the
current 'iterator_adaptor_test.cpp' (my formatting), followed by a
re-written version that I personally find more understandable/less
error-prone:

// original code
typedef boost::iterator_adaptor<
    boost::forward_iterator_archetype<dummyT>
  , boost::default_iterator_policies
  , dummyT
  , const dummyT&
  , std::forward_iterator_tag
  , std::ptrdiff_t
  , const dummyT*
> adaptor_type;

// the same code that uses traits and "named template parameters";
// one can omit any of the named parameters or change their order;
// any changes in the order of the template "real" default parameters
// are completely transparent.

typedef boost::iterator_adaptor<
  , boost::default_iterator_policies
  , boost::iterator_traits_builder<
boost::forward_iterator_archetype<dummyT> >
      ::value<dummyT>
      ::reference<const dummyT&>
      ::category<std::forward_iterator_tag>
      ::distance<std::ptrdiff_t>
      ::pointer<const dummyT*>
> adaptor_type;

The 'iterator_traits_builder' template might look like this (it is a little
bit complicated/large because the original 'iterator_adaptor' part wasn't
small too):

template<
  class Base
, class Value = BOOST_ARG_DEPENDENT_TYPENAME
boost::detail::iterator_traits<Base>::value_type
, class Reference = BOOST_ARG_DEPENDENT_TYPENAME
boost::detail::iterator_defaults<Base,Value>::reference
, class Category = BOOST_ARG_DEPENDENT_TYPENAME
boost::detail::iterator_traits<Base>::iterator_category
, class Distance = BOOST_ARG_DEPENDENT_TYPENAME
boost::detail::iterator_traits<Base>::difference_type
, class Pointer = BOOST_ARG_DEPENDENT_TYPENAME
boost::detail::iterator_defaults<Base,Value>::pointer
> struct iterator_traits_builder {

  typedef Base base_type;
  typedef Distance difference_type;
  typedef typename boost::remove_const<Value>::type value_type;
  typedef Pointer pointer_type;
  typedef Reference reference_type;
  typedef Category iterator_category;

  template<class U> struct value : iterator_traits_builder<U,
Reference, Category, Distance, Pointer> {};
  template<class U> struct reference : iterator_traits_builder<Value, U,
Category, Distance, Pointer> {};
  template<class U> struct category : iterator_traits_builder<Value,
Reference, U, Distance, Pointer> {};
  template<class U> struct distance : iterator_traits_builder<Value,
Reference, Category, U, Pointer> {};
  template<class U> struct pointer : iterator_traits_builder<Value,
Reference, Category, Distance, U> {};
};

Summary: I would be really grateful, if Dave and Jeremy considered a
possibility to add/adopt the named template parameters interface to the
current version of iterator adaptors library.

And, at last, just an aside note - I am not the author of the technique; it
seems that it was known back to 1998 (at least
http://www.extreme.indiana.edu/~tveldhui/papers/oo98.html#200 seems to refer
to the same thing); however, I am surprised that I've never seen it before I
reinvented it myself (I found the above link just a few minutes ago).

Aleksey


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