|
Boost : |
From: David Abrahams (abrahams_at_[hidden])
Date: 2000-11-01 13:14:47
From: "Peter Dimov" <pdimov_at_[hidden]>
> Dave wrote:
> > We recognized the problem, then spent a bunch of time trying to figure
> out
> > why partial specialization might be better than allowing overloading.
> > Eventually, we came across this case posted by Peter Dimov to
> c.l.c++.m:
> >
> > template <class T> void f(T); // #1
> > template <> void f<int*>(int*); // #2
> > template <class T> void f(T*); // #3
> >
> > int *x;
> > f(x); // which one gets called? #3, surprisingly
>
> To clarify, you felt that this example is an argument in favour of
> allowing std:: overloading and not allowing partial specializations?
Not exactly. I felt that it showed that mixing specialization and
overloading can produce confusing results, at least to someone without a
deep understanding of what's going on. Certainly, quite a few committee
members were surprised.
> > It seems to me that the confusion comes from mixing overloading and
> > specialization. The two mechanisms don't play well together. Since IMO
> few
> > people have been writing function specializations anyway, and it's a
> problem
> > we can solve entirely in the LWG without a change to the core
> language, it
> > would be better to allow overloading in std and discourage
> specialization of
> > function templates.
>
> But note that allowing
>
> struct base {};
>
> namespace std
> {
> void swap(base &, base &);
> }
>
> would let the following compile, if I'm not mistaken:
>
> struct derived: base {};
>
> base b;
> derived d;
>
> std::swap(b, d);
>
> An overload in this case cannot satisfy 17.4.3.1/1, "meets the standard
> library requirements for the original template" - the original template
> does not work for different types.
I think you're reading the standard too broadly. The language above doesn't
prohibit the overload from having additional functionality (e.g. working
with different types). But in any case the language you quote isn't designed
for overloading, but for specialization.
> This is the primary advantage of specializations (partial or explicit)
> over overloads - they have exactly the same interface as the original
> template.
An advantage, to be sure, and not to be understated. A big disadvantage of
using function template specialization is that the most obvious syntax to
use makes it order-dependent:
template <class T> void f(T); // #1
template <> void f<int*>(int*); // #2
template <class T> void f(T*); // #3
#2 specializes #1, but:
template <class T> void f(T); // #1
template <class T> void f(T*); // #3
template <> void f<int*>(int*); // #2
Now #2 specializes #3. Since the specialization for a user-defined type is
likely to live in a header with the user-defined type declaration, semantics
become subject to the vagaries of #include order. Of course, there's a way
around this (though I don't remember the syntax), but it takes a lot more
discipline.
> > Core has also discussed this. Some in core thought that it was an
> obvious
> > omission that partial specialization of function templates was not
> allowed,
> > but eventually they had a problem with this particular proposal
> because it
> > was not always clear from the proposed syntax exactly what might be
> > specialized.
>
> Did they show a concrete example of an ambiguity? I was pretty certain
> at the time that a partial specialization declaration can never be
> ambiguous.
No, we only had an informal discussion between the two working groups. I"ve
forwarded this mail to Steve Adamczyk and John Spicer, the EDG guys who
raised the objection. Maybe they can fill in the details.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk