|
Boost : |
From: David Abrahams (david.abrahams_at_[hidden])
Date: 2002-02-19 17:48:29
----- Original Message -----
From: "brianjparker" <brianjparker_at_[hidden]>
> --- 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 not-infrequent 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
meta-lambda 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 - compile-time lambda facility allows you to
workaround this often-cited 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 compile-time 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.. :)
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk