G++ bug: template c'tors
llewelly@198.dsl.xmission.com
llewelly@198.dsl.xmission.com
Fri Dec 31 20:54:00 GMT 1999
On Sun, 19 Dec 1999, Ken Yarnall wrote:
>
>
> llewelly@198.dsl.xmission.com wrote:
> >
> > On Sun, 19 Dec 1999, Ken Yarnall wrote:
> >
> > > With this code:
> > >
> > > ----------------gccerr.cpp---------------------
> > > class Err
> > > {
> > > public:
> > >
> > > template <class FPtr>
> > > Err(FPtr f) {}
> > > };
> > >
> > > class Umm {
> > > public:
> > > Umm(const Err& e)
> > > : err(e)
> > > {}
> > >
> > > void doit() {}
> > >
> > > private:
> > > Err err;
> > > };
> > >
> > > void f()
> > > {}
> > >
> > > int main()
> > > {
> > > Umm u(Err(f));
> >
> > Allow me to clarify the above line code by removing superflous
> > parentheses:
> >
> > Umm u(Err f);
> >
> > Looks like a function decl, doesn't it? Well, that's what the ISO C++
> > standard says it is. 'Umm' is the return type. 'u' is the function
> > name. 'Err' is type of the first parameter. 'f' is the name of the
> > first parameter. The '()' around the f are superflous.
> >
> > This resolution was considered necessary for backwards compatibility with
> > C89.
> >
> > In other words, this is a bug in the c++ definition, not in g++.
>
> I can even remember reading about that somewhere, now. Thanks for the explanation.
> What a terrible idea, though; the reason I thought it was a bug what that in the
> actual code, I have a similar example with a two-argument constructor, which is
> interpreted "correctly" by the parser. The lack of regularity is a real wart.
Yes, it is.
The question to ask yourself is 'Are my constructor arguments also
typenames?' In your previous example, 'Err' is a typename. If one of the
constructor args is clearly not a typename, C++ will interpret it as a
constructor call. Otherwise, it is a function decl.
>
> Is there no way to construct a temporary in-line like this with a one-arg c'tor?
Hm. Try:
Umm u(f);
This relies on the fact that the single arg constructor Err<>::Err() is
also an implicit conversion function (if you don't like this, make it
'explicit'), so the compiler will use it to automagically convert f to
type Err<void(*)()> .
If you need to declare your single arg constructor as explicit (because
you may not want it to be used for implicit conversions) try:
Umm u(static_cast<Err>(f));
Both of the above call the constructor, and work as one would expect,
using gcc 2.95.2 .
More information about the Gcc-bugs
mailing list