Boost logo

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