Boost logo

Boost :

From: David B. Held (dheld_at_[hidden])
Date: 2002-10-04 16:14:12


"Aleksey Gurtovoy" <agurtovoy_at_[hidden]> wrote in message
news:4034600A4760D411B8720001031D84FB01096494_at_postoffice.office.meta...
> [...]
> Yes, in the simplest case; basically you spell out a metafunction with
some
> arguments filled and some missing:
>
> typedef is_same<_,int> f;

I think what's really throwing me off is that it looks like the lowly
underscore
has been elevated to a place of great prominence. I didn't even think it
was
a legal C++ identifier, let alone some magical placeholder.

> and MPL allows you to convert it to metafunction-class - and after that
you
> can do whatever you want with it:
> [...]

To be honest with you, I think all this stuff should go in the docs
somewhere
as an example. I think it makes mpl::lambda a lot easier to understand.

> [...]
> template <
> typename T
> , typename OwnershipPolicy
> , typename ConversionPolicy
> , typename CheckingPolicy
> , typename StoragePolicy
> , typename sp_ = typename apply<StoragePolicy,T>::type
> >
> struct smart_ptr
> : sp_
> , apply<OwnershipPolicy, typename sp_::pointer_type>::type
> , apply<CheckingPolicy, typename sp_::pointer_type>::type

I assume these are mpl::apply<>? Otherwise, nice illustration. It's
starting
to sink in.

> [...]
> And here's an equivalent definition that accepts both meta-function
classes
> and lambda expressions:
>
> template< typename F, typename T > struct le_apply
> {
> typedef typename mpl::lambda<F>::type f_;
> typedef typename mpl::apply1<f_,T>::type type;
> };
>
> template <
> typename T
> , typename OwnershipPolicy
> , typename ConversionPolicy
> , typename CheckingPolicy
> , typename StoragePolicy
> , typename sp_ = typename le_apply<StoragePolicy,T>::type
> >
> struct smart_ptr
> : sp_
> , le_apply<OwnershipPolicy, typename sp_::pointer_type>::type
> , le_apply<CheckingPolicy, typename sp_::pointer_type>::type
> {
> // ...
> };
>
> // usage
>
> // policies can have form of both ordinary class templates...
> template< typename T >
> struct ownership_policy1
> {
> //...
> };
>
> // ...and metafunction-classes
> struct conversion_policy1
> {
> template< typename T > struct apply
> {
> //...
> };
> };
>
> // ...
> typedef smart_ptr< my
> , ownership_policy1<_>
> , conversion_policy1
> , ...
> > my_ptr;
>
> // and they can take pretty sophisticated forms as well
> typedef smart_ptr< my
> , ownership_policy1< add_const< add_pointer<_> > >
> , conversion_policy1
> , ...
> > my_const_ptr;

This is like epic poetry! You are the Homer of C++! (And I don't mean
the donut-eating Duff beer-belching one, either ;). Ok, I actually see
what's
going on now. You turn the template-based policies into actual classes
with the placeholder(s). And then once they pass through the "class
boundary", they reassert their template nature through the lambda system.
If that isn't magic, then I don't know what is. However, I notice that in
one
place, you used apply<>, and another, apply1<>. Is apply<> a generic
wrapper for any arity, and apply1<> a specialized version for just one
argument?

> > In fact, that code looks like pure magic to me...
>
> It's because it is pure magic :).

But is it white magic, or black magic? I won't ask if you had to sell your
soul to write this library. ;)

> [...]
> Well, I hope the above clarifies things a little bit.

Yes, it is excellent. I think I understand mpl::lambda enough to integrate
it with the smart pointer. Thanks a lot for the tutorial. It think it is
better
that template templates go away now. I hope Andrei doesn't mind.

Dave


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