[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug c++/14502] [3.3 Regression] g++ compile fails "no matching function
From: |
bangerth at dealii dot org |
Subject: |
[Bug c++/14502] [3.3 Regression] g++ compile fails "no matching function" using forward declaration of class involving inheritance |
Date: |
10 Mar 2004 22:42:10 -0000 |
------- Additional Comments From bangerth at dealii dot org 2004-03-10 22:42
-------
This is actually an interesting problem, and I'm not at all convinced
that we do the right thing. Here's a redux:
-----------------
template <class T> struct B {};
template <class T> void bar ()
{ B<T> *p = (T*)0; }
struct D;
int foo() { bar<D>(); };
struct D : public B<D> {};
int i = foo();
---------------------
Now, 3.2.3 compiles this as do 3.4 and mainline, but 3.3.4 doesn't. My
grapples with this are: when we see foo(), we realize that this is not
a template, so we should expand its body. At this time, D is only
forward declared, so when we instantiate bar<D> we realize that we are
asked to convert a D* to a B<D>* in the assignment. 3.3.x tells us
g/x> /home/bangerth/bin/gcc-3.3*/bin/c++ -c x.cc
x.cc: In function `void bar() [with T = D]':
x.cc:8: instantiated from here
x.cc:4: error: cannot convert `D*' to `B<D>*' in initialization
I believe this is a sensible error message, since at the time of instantiation
of bar<D>, we are unaware of the fact that D is actually derived from B<D>
and that therefore a D* _can_ be converted into a B<D>*.
So apparently the confusion all comes from the fact that 3.3 tries to
expand the body of foo() when it sees the function definition, while all
other versions of the compiler only try to do so when this function is
actually used or at the end of the compilation unit. This is supported by
the fact that if we remove the last definition of D and of the variable i
from the file, then suddenly also the other compilers get into trouble.
So, in my view 3.3 is actually the only version that gets it right, i.e.
expands the body of the function at the point of its definition; we probably
all agree that this is the sensible thing to do for non-templates. All other
versions defer expansion of the body of bar() until the end of the translation
unit, at which point the definition of D is already known. In other words,
we would have an accepts-invalid in 3.2.3, 3.4 and mainline (and thus a
regression), not a rejects-valid in 3.3.
Does this all sound sensible?
W.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14502