Boost logo

Boost :

From: Douglas Gregor (dgregor_at_[hidden])
Date: 2007-10-23 08:42:49


Stjepan Rajko wrote:
> For my specializable functions, I adapted what is used in fusion, e.g.:
>
> template<typename ProducerTag, ConsumerTag>
> struct operation_impl;
>
> template<>
> struct operation_impl<some_producer_tag, some_consumer_tag>
> {
> template<typename P, typename C>
> struct apply
> {
> typedef some_result_type type;
>
> static type call(P &p, C &c)
> {
> ...
> }
> };
> };
>
IIRC, using this form makes operation_impl<some_producer_tag,
some_consumer_tag> into an MPL metafunction class, which makes it usable
with all of the various metafunction algorithms. That's important if you
need to use MPL algorithms across sequences of producer/consumer types.
> template<>
> struct operation_impl<some_producer_tag, some_consumer_tag>
> {
> // specify result type using result_type typedef or template<> struct result
> // ...
>
> template<typename P, typename C>
> some_result_type operator()(P &p, C &c)
> {
> ...
> };
> };
>
The advantage of this one relative to the first one is that, here,
operation_impl<some_producer_tag, some_consumer_tag> is a function
object while the first one requires you to dig out the ::apply<P, C>
member and use the static "call". However, this version doesn't provide
direct interoperability with MPL.

> , or the technique described in:
> http://www.boost.org/more/generic_programming.html,
>
> or any other tag dispatching convention I should be aware of?
>
I still prefer the technique described at the web page you mention,
because it's more robust with the evolution of the concepts in the
library. For example, note in the advance() example there that we only
provide advance_dispatch overloads for input_iterator_tag,
bidirectional_iterator_tag, and random_access_iterator_tag. However, the
actual tag "hierarchy" looks like this:

  struct input_iterator_tag { };
  struct output_iterator_tag { };
  struct forward_iterator_tag : virtual input_iterator_tag, virtual
output_iterator_tag { };
  struct bidirectional_iterator_tag : virtual forward_iterator_tag { };
  struct random_access_iterator_tag : virtual bidirectional_iterator_tag
{ };

Notice that an iterator with that forward_iterator_tag will still work
with the tag-dispatching approach from the web page (because of the
implicit conversion from forward_iterator_tag to input_iterator_tag). To
make this work with the specialization-based approach used in the top
two examples you gave, you would have to add an extra specialization for
forward_iterator_tag. That's only a little extra work, but it would have
to be done any time someone introduces a new concept, e.g.,

  struct contiguous_iterator_tag : virtual random_access_iterator_tag { };

    - Doug


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