
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