gcc/kcc difference

Joe Buck jbuck@synopsys.COM
Wed Dec 15 12:40:00 GMT 1999


nbecker writes:

> In porting my code from g++-2.95.1 to kcc I noticed the following.

Squashed version of the example:

struct A {
	static int Unipolar(int);
	template<class X> int B(X x) { return Unipolar(x);} // "line 7"
};
int Unipolar(int);

> gcc-2.95.1 accepts this without complaint.  But KCC-3.4 says:
> 
> "../bug2.cc", line 7: error: more than one instance of overloaded function
>           "Unipolar" matches the argument list:
>             function "Unipolar(int)"
>             function "A::Unipolar(int)"
>             argument types are: (int)
>       return Unipolar(x);
>              ^
>           detected during instantiation of "int A::B(X) [with X=int]" at line
>                     17

> Which is correct?

I believe that gcc-2.95.1 is correct and KCC is wrong.  The reason is
that, as Stroustrup puts it, overloading is not applied across different
scopes.  Declaring the name "Unipolar" in class A hides all instances
of that name outside class A, so only A::Unipolar(int) should be visible
at that point.

There is a complication for templates, having to do with dependent names,
which are bound at the point of instantiation, and independent names,
which are bound at the point of expansion.  But I can't find any
interpretation of those rules that would suggest that the global Unipolar
should be considered.  Unipolar does not depend on the template argument
X, which says the name is bound at point of definition, and there is
only one Unipolar.  But perhaps I'm wrong, because this is a member
template.  Maybe names that depend on A also count as dependent.  Well,
then Unipolar is looked up at the point of instantiation.  But at that
point, A::Unipolar still shadows ::Unipolar.

In fact, Stroustrup goes so far as to assert in C.13.8.2 of his "Third
Edition" that if a declaration is found when a template is parsed, it is
used even if a better declaration might be found later (I know, it's
non-normative, meaning "not the standard").  His example:

void g(double);
template<class T> class X : public T {
public:
	void f() { g(2);} // call g(double);
	...
};

void g(int);
class Z { };
void h(X<Z> x)
{
	x.f();
}

In this case he says that g(double) will still be called even though
g(int) is an exact match.





More information about the Gcc mailing list