Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2002-12-31 17:25:44


----- Original Message -----
From: "David Abrahams" <dave_at_[hidden]>

> "Jaap Suter" <J.Suter_at_[hidden]> writes:
>
> >> Nifty! You're using one of my favorite metaprogramming tricks, the
> >> default template parameter which allows you to avoid creating a
> >> separate implementation template. I almost forgot about that one,
> >> it's been so long since I've been able to use it.
> >
> > Funny you mention that. I've been meaning to ask for its appropriateness
on
> > this list. After all, we are exposing implementation details in the
> > interface which is not something I would recommend on a daily basis.
Glad
> > you like it :).
>
> That's a good point. It's a question of overall clarity. If it's
> clearer to dispatch to an implementation template, I would say "do
> it".

I do this type of thing all the time:

namespace hidden_default_template_parameter {

class hidden {
    enum type { };
    friend class access_rights;
};

struct obtuse_access_rights {
    typedef hidden::type type;
};

} // hidden_default_template_parameter

#define HIDE \
    HIDE_ID( \
        hidden_default_template_parameter::obtuse_access_rights::type; \
    ) \
    /**/

#define HIDE_ID(id) id = id(),

template<class T, HIDE class U = T> struct sample {
    // ...
};

In other words, a user cannot specify the 'U' parameter without also
specifying the parameter generated by 'HIDE'. This method is not
bulletproof, because the user can still do this:

sample<int, hidden_default_template_parameter::obtuse_access_rights::type(),
double>

...but that is pretty obtuse.

In order to make it bulletproof and still avoid the recursive template
instantiation, you have to do something like this:

class sample {
    private:
        enum type { };
    public:
        template<class T, type = type(), class U = T>
        struct _ {
            // ...
        };
};

...and use it like this:

sample::_<int>

There is no way that the user can specify the second parameter in this case.
Only the default can be used. Likewise, barring keyword arguments, the
third parameter must use the default as well. Of course, I like the first
version better even though it isn't bulletproof. The implementation itself
is reusable, it doesn't change the usage syntax, and at least it's obvious
that the parameter is not supposed to be used. Maybe "BOOST_HIDE_DEFAULT"?

template<class T, BOOST_HIDE_DEFAULT class U = T> struct XYZ { };

2c
Paul Mensonides


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