|
Boost : |
From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-10-08 02:52:09
David B. Held wrote:
> > Hhm, how about this one:
> >
> > template< typename Policy >
> > struct ownership_policy
> > {
> > typedef Policy type;
> > typedef ownership_policy_tag policy_category;
> > };
> >
> > template< typename T >
> > struct ref_counted
> > : ownership_policy< ref_counted<T> >
> > {
> > // ...
> > };
>
> Well, that seems obvious enough, but I thought that the fact
> that the type typedef used the name of the template is what
> allowed you to rebind it without a rebind template.
Nope, it just couldn't, because
template< typename T > struct her
{
typedef her type;
};
is exactly the same thing as
template< typename T > struct her
{
typedef her<T> type;
};
> But now that I think of it, that would mean you
> have a template typedef, which is magical indeed.
Yeah; if we had template typedefs, to make 'type' one of them we would have
to spell it like this:
template< typename T > struct her
{
typedef ::her type; // in global scope 'her' is a template
};
Actually, here is a curious GCC feature:
template< typename T > struct her
{
typedef her type;
};
// GCC only
// her<int>::type is treated either as a type or
// as a class template, depending on the usage
// GCC only
// her<int>::type is treated either as a type or
// as a class template, depending on the usage:
// ok, nothing unusual
typedef her<int>::type t1; // t1 == int
// here:
typedef her<int>::type<long>::type t2; // t2 == long!
// of course, this one doesn't work
// typedef t1<bool>::type t3; // error
Fascinating, IMO. It was Emily who discovered it (I wouldn't be able to even
imagine that something like this is possible to try it out :).
> So I guess I don't understand how the type field works,
> and how you get a concrete class to rebind in lambda
> (without a rebind template, of course).
By template class introspection via template template parameters and partial
specialization:
// default pass-through branch
template< typename T > struct lambda
{
typedef T type;
};
template<
template< typename P1 > class F
, typename T1
>
struct lambda< F<T1> >
{
// now we have 'F', we can do something ...
};
template<
template< typename P1, typename P2 > class F
, typename T1, typename T2
>
struct lambda< F<T1,T2> >
{
// ...
};
// user code
template< typename T > struct her
{
};
typedef lambda< her<long> >::type l;
There are complications, but the basic idea is pretty simple.
Aleksey
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk