Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-02-28 07:18:09


Beman Dawes wrote:
> That seems like a possibly interesting technique.
> Unfortunately, I got
> quite lost trying to follow it. The complexities of
> iterator_adaptor,
> broken compiler workarounds, and typos all conspired to put
> me into a state
> of confusion.
>
> Could you please give a more tutorial example?

The basic idea is that for every default template parameter 'T#i' of the
original template A you define the corresponding nested class template
'param_#i' and inherit it from a partial specialization (?) of the A
template using the following formula:

template<class U> struct param_#i : public A< T#j for all i != j, U for i ==
j > {};

For instance:

template<class T1 = char, class T2 = int, class T3 = long>
struct A {
template<class U> struct param_1 : A<U, T2, T3> {};
template<class U> struct param_2 : A<T1, U, T3> {};
template<class U> struct param_3 : A<T1, T2, U> {};

typedef T1 type_1;
typedef T2 type_2;
typedef T3 type_3;
};

typedef A<> a1;
BOOST_STATIC_ASSERT((is_same<a1::type_1, char>::value));
BOOST_STATIC_ASSERT((is_same<a1::type_2, int>::value));
BOOST_STATIC_ASSERT((is_same<a1::type_3, long>::value));

typedef A<>::param_3<void>::param_1<double> a2;
BOOST_STATIC_ASSERT((is_same<a2::type_1, double>::value));
BOOST_STATIC_ASSERT((is_same<a2::type_2, int>::value));
BOOST_STATIC_ASSERT((is_same<a2::type_3, void>::value));

Hmm, the above is probably even worse than 'iterator_adaptor' example :(. As
something less abstract and more useful, below is an 'iterator_typedefs'
sample:

template<
    class Category_ = std::input_iterator_tag
  , class ValueType_ = void
  , class Distance_ = std::ptrdiff_t
  , class Pointer_ = ValueType_*
  , class Reference_ = ValueType_
>
struct iterator_typedefs_base
  : std::iterator<Category_, ValueType_, Distance_, Pointer_, Reference_> {

  template<class U> struct Category : iterator_typedefs_base<U,
ValueType_, Distance_, Pointer_, Reference_> {};
  template<class U> struct Value_type : iterator_typedefs_base<Category_, U,
Distance_, Pointer_, Reference_> {};
  template<class U> struct Distance : iterator_typedefs_base<Category_,
ValueType_, U, Pointer_, Reference_> {};
  template<class U> struct Pointer : iterator_typedefs_base<Category_,
ValueType_, Distance_, U, Reference_> {};
  template<class U> struct Reference : iterator_typedefs_base<Category_,
ValueType_, Distance_, Pointer_, U> {};
};

struct iterator_typedefs : iterator_typedefs_base<> {};

struct my_int_iterator : iterator_typedefs
  ::Value_type<int>
  ::Category<std::input_iterator_tag>
  ::Pointer<int*>
  {
  };

BOOST_STATIC_ASSERT((is_same<my_int_iterator::value_type, int>::value));
BOOST_STATIC_ASSERT((is_same<my_int_iterator::iterator_category,
std::input_iterator_tag>::value));
BOOST_STATIC_ASSERT((is_same<my_int_iterator::pointer, int*>::value));

BTW, I don't like mixed case there, but for now I don't know any other way
to get around hiding of the original (inherited) typedefs' names in case of
lowercase "named parameters" names..

Anyway, I hope that at least one of the above examples is more or less
satisfactorily understandable :). Actually there are much more things to be
said about the technique than these examples, but being busy with my work
and trying to get boost metaprogramming library ready for the first review,
I can only dream about writing down all the details.. I have a short
motivational "article", though, if anyone is interested to get it further..

Aleksey


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