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