
Boost : 
From: brianjparker (brianjparker_at_[hidden])
Date: 20020219 21:44:17
 In boost_at_y..., "David Abrahams" <david.abrahams_at_r...> wrote:
>
>  Original Message 
> From: "brianjparker" <brianjparker_at_h...>
>
>
> >  In boost_at_y..., Carl Daniel <cpdaniel_at_p...> wrote:
> > > I'd like to see the rule for template template argument
> > compatibility relaxed (e.g. such that std::vector<T,A=allocator>
> > > and myclass<T> would both be compatible with a template template
> > parameter declared as template <class>). The current
> > > rule appears to have been adopted to better meet with users
> > expectations (as compared to function pointer
> > > compatibility). The notinfrequent threads on c.l.c++.m about
this
> > subject suggest that it did just the opposite:
> > > institutionalized behavior which is counter to expectations and
> > unnecessarily limiting.
> >
> > I totally agree with this; in fact I would consider this change to
> > more of a bug fix than a language extension. The main negative
effect
> > of the current rule is that it prevents future library classes
from
> > adding additional template arguments with defaults whilst still
> > remaining backwardly compatible.
>
> FWIW, both gcc and Borland "work" the way you'd like, and that bug
cripples
> metalambda expressions in MPL on those compilers. Before you buy
into this
> change you should consider this example Aleksey sent me today:
>
> 
>
> template< template<typename> class F > struct my {};
> template<typename T, typename U = T> struct her {};
>
> int main()
> {
> sizeof(my<her>); // should not compile, but ok with
GCC/Borland
> return 0;
> }
>
>
> BTW, it's kind of ironic  compiletime lambda facility allows you
to
> workaround this oftencited inflexibility of template template
parameters,
>
> template< typename F >
> struct my
> {
> // same as 'typedef F<int> t' if F would be a TTP
> typedef typename lambda<F>::type f_;
> typedef typename apply1<f_,int>::type t;
> };
>
> template<typename T, typename U = T> struct her {};
>
> int main()
> {
> sizeof(my< her<_1> >); // ok!
> return 0;
> }
>
> and is, in fact, superior to the GCC and Borland behavior, because
with
> lambda it's possible to do an arbitrary currying,
>
> sizeof(my< her<int,_1> >); // ok too!
>
> and yet this inflexibility it so successfully fights with seems to
be a very
> important part on the library's own implementation :).
>
> > You're saying that the compiletime lambda doesn't actually
> > work with GCC because it needs working TTP to implement
> > it?
>
> It works with anything but currying of class templates that have
default
> template parameters, e.g.
>
> template< typename T, typename U > struct my {};
> template< typename T, typename U = int > struct her {};
>
> typedef typename lambda< my<_1,int> >::type t1; // ok
> typedef typename lambda< her<_1> >::type t2; // #1  the
ambiguity error
> we've talked about
>
> Unfortunately, MPL uses the default template parameters for almost
every
> predefined function object like 'logical_or' or 'plus' (to support
more
> invocations with than 2 arguments)..
>
> > If so, that doesn't make sense to me because we know we
> > can always replace TTP with generators.
>
> It's matching of the class template specializations like
>
> template< typename T >
> struct lambda
> {
> typedef T type;
> };
>
> template<
> typename T
> , template< typename > class F
> >
> struct lambda< F<T> >
> {
> typedef /**/ type;
> };
>
> template<
> typename T1
> , typename T2
> , template< typename, typename > class F
> >
> struct lambda< F<T1,T2> >
> {
> typedef /**/ type;
> };
>
> that cause GCC to fail in line #1, and I am afraid there is no way
we can
> get away with generators here.. :)
Hmmm, certainly if the suggested change would break real existing
code, as in this example, then that is a strong argument against it.
Admittedly without having looked into the implementation of MPL, I
wonder if the problem in the quoted example is just that the partial
specialisation ordering rules need tweaking. I would have expected
that her<_1> would preferentially match
template<
typename T1
, typename T2
, template< typename, typename > class F
>
struct lambda< F<T1,T2> >
{
typedef /**/ type;
};
over the single argument template version, in which case there would
be no ambiguity. Is this not the case in the gcc implementation?
If that was the specified behaviour then would the MPL code work OK?
(Please excuse me if I have completely missed the point of the
example)
,Brian Parker
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk