Boost logo

Boost :

From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-12-07 03:06:58


David A. Greene wrote:
> But consider this testcase:
>
> //#define CT_DEBUG
>
> //#include "ct_print.hh"
> #include <boost/mpl/placeholder.hpp>
> #include <boost/mpl/lambda.hpp>
>
> template<typename T, typename U, typename V>
> struct my_type {
> };
>
> template<typename T, typename U, typename V>
> struct my_type_generator {
> typedef my_type<T, U, V> type;
> };
>
> template<template<typename, typename, typename> class Base,
> typename T, typename U, typename V>
> struct trivial_generator {
> typedef Base<T, U, V> type;
> };
>
> int main(void)
> {
> typedef my_type_generator<char, short, int> generator;
> //CT_PRINT(my_type_generator_result_is, generator::type);
>
> typedef trivial_generator<my_type, char, short, int> t_generator;
> //CT_PRINT(trivial_generator_result_is, t_generator::type);
>
> // Try to make some generators
> typedef boost::mpl::lambda<my_type_generator<char, boost::mpl::_1,
> boost::mpl::_2> >::type lambda_generator;
> typedef lambda_generator::apply<short, int> lg_apply_result;
> //CT_PRINT(lambda_generator_result_is, lg_apply_result::type);
>
> // Does not work
> typedef boost::mpl::lambda<trivial_generator<my_type, char,
> boost::mpl::_1, boost::mpl::_2> >::type lambda_trivial_generator;
> // g++ 3.2 claims apply doesn't exist.
> typedef lambda_trivial_generator::apply<short, int> ltg_result;
> //CT_PRINT(lambda_trivial_generator_result_is, ltg_result::type);
>
> return(0);
> }
>

That's because the MPL's lambda works only with metafunctions which template
parameters are _types_, and only types:

1) a "canonical" metafunction, OK:

    template< typename T > struct identity
    {
        typedef T type;
    };

    typedef lambda< identity<_> >::type f;
    BOOST_MPL_ASSERT_IS_SAME(f::apply<int>::type, int);

2) a metafunction with non-type template parameter, can't be used in lambda
expressions:

    template< typename T, int i = 0 > struct identity
    {
        typedef T type;
    };

    typedef lambda< identity<_> >::type f;
    BOOST_MPL_ASSERT_IS_SAME(f::apply<int>::type, int); // error!

3) a metafunction with template template parameter, can't be used in lambda
expressions:

    template< typename T > struct something;
    template< typename T, template< typename > class F = something > struct
identity
    {
        typedef T type;
    };

    typedef lambda< identity<_> >::type f;
    BOOST_MPL_ASSERT_IS_SAME(f::apply<int>::type, int); // error!

Strictly speaking, (2) and (3) are not even metafunctions in MPL's
terminology.

>
> >>But I can construct a generic trivial generator:
> >>
> >>template<template<typename A, typename B, typename C> class Base,
> >> typename T, typename U, typename V>
> >>struct trivial_generator {
> >> typedef Base<T, U, V> type;
> >>};
> >>
> >>Then I can use MPL lambda facilities. Unfortunately, I need a
> >>trivial_generator for every arity of class template.
> >
> > Only as part of the implementation. You just need a nice
> > wrapper over the top to hide it all.
>
> Right. Can you point me to the MPL equivalent as a guide of
> how to do this?

Actually, even ignoring the aforementioned lambda issue, it's not possible
to write a single template (a wrapper or not) that would take template
template parameters of different arity - if it were, the library itself
would use the technique to implement the single 'quote/mem_fun' template
instead of providing the family of 'mem_fun1', 'mem_fun2', etc. constructs.

It _is_ possible to implement a single template along the lines of the
SHAZAM template you've mentioned early in the thread:

    template<typename T, typename U, typename V>
    struct my_type { ... } // Note: no ::type member

    typedef SHAZAM<my_type<int, _1, _2> > generator;

    typedef generator::template apply<char, float>::type my_type_inst;

but not at the user side - the library internal mechanisms needs to be made
aware of it. I considered this before, - as well as the option of directly
supporting the "reduced" metafunction form, - and the latter is currently my
preference. Will see if something changes after I actually implement it (for
one, it might slow down the lambda significantly, - but we'll see).

Aleksey


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