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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to