Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2002-02-06 20:49:25


On Wednesday 06 February 2002 08:15 pm, you wrote:
> What is wrong with forwarding classes (until typedef templates make it into
> the language)?
>
> template <typename T>
> struct specific_a : public generic<T, policy_a>
> { ... forwarding ctors, etc. };
>
> template <typename T>
> struct specific_b : public generic<T, policy_b>
> { ... forwarding ctors, etc. };
>
> At the cost of having to write and maintain more code, doesn't the above
> simulate:
>
> template <typename T>
> typedef generic<T, policy_a> specific_a;
>
> template <typename T>
> typedef generic<T, policy_b> specific_b;
>
> Or am I missing something?
>
> --Beman

The problem is almost entirely a maintenance problem, because it can require
a huge amount of maintenance. This is the way Boost.Function works, and it
has been a maintenance nightmare. Here's a glimpse into what Boost.Function
needs:

----------------
function();
template<typename Functor> function(Functor f);
function(const base_type& f);
function(const self_type& f);
         
template<typename Functor> self_type& operator=(Functor f);
self_type& operator=(const base_type& f);
self_type& operator=(const self_type& f);

template<typename Functor> void set(Functor f);
void set(const base_type& f);
void set(const self_type& f);
----------------

Note that even some normal member functions need to be forwarded in some
cases.

There's a bigger problem lurking - how does the user specialize when using
forwarded classes? E.g., if I write:

template<typename T>
struct my_class<specific_a<T> > {};

this partial specialization won't match to generic<T, policy_a>, whereas a
template typedef would. And, of course,

template<typename T, typename Policy>
struct my_other_class<generic<T, Policy> > {};

won't be matched by specific_a<T>.

Note 1: generator-based solutions don't have either of the above problems,
because you can't create a partial specialization for something like
generator<T>::type.

Note 2: Boost.Function is somewhat unique in that it doesn't suffer from the
specialization problem, because a user cannot determine how many template
parameters Boost.Function has to specialize based on. Something like:

template<typename R, typename T1, typename T2, ..., typename TN>
struct my_class<boost::function<R, T1, T2, ..., TN> > {};

is ill-fated from the start, because N isn't really available.

        Doug


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