Software Archive
Read-only legacy content
17061 Discussions

ICPC failing to compile name hiding of overloads

Martin_K_6
Beginner
410 Views

Hi,

I am postin this in the MIC forum, though the issue is not MIC-specific as it concerns the compiler frontend. The attached code demostrates a case of ICPC (both 14.0.0 and 13.1.1) failing to compile a particular setup of overloaded method hiding. The error message produced is:

$ icpc bug.cpp

bug.cpp(171): error: more than one instance of overloaded function "ClassC::foo" matches the argument list:

function template "ClassC &ClassC::foo(const ClassB &, const ClassD &)"

function template "ClassC &ClassB::foo(const ClassB &, const ClassD &) [with NUM_T=42U, SUBCLASS_T=ClassC]"

argument types are: (Offender, ClassE)

object type is: Offender Offender a = Offender().foo(Offender(), ClassE());

                                                                     ^

compilation aborted for bug.cpp (code 2)

$

0 Kudos
4 Replies
Judith_W_Intel
Employee
410 Views

 

This is a small reduced example. The ambiguity error message looks correct to me (and the Microsoft compiler gives a similar error).

template < typename SUBCLASS_T >
struct ClassB
{
   template < typename ANYCLASS0_T>
   void foo(ClassB< ANYCLASS0_T >);
};


struct ClassC : public ClassB< ClassC >
{
   template < typename ANYCLASS0_T>
   void foo( ClassB< ANYCLASS0_T >); // GNU prefers this overload for some reason (probably a GNU bug)

   using ClassB< ClassC >::foo;
};

int main()
{
  ClassC c;
  c.foo(c);
  return 0;
}

It looks like GNU prefers the foo inside classC over the one brought in the by the using declaration in classA. So we will fix this

as a GNU compatibility bug (but you really should consider fixing the code) .. This is entered in our bug tracking database as DPD200248535.

Judy

0 Kudos
Martin_K_6
Beginner
410 Views

Thank you for the reduction, but I'm not quite following your reasons for pinning this issue on gnu compatibility.

Clearly ClassC::foo() hides any foo() (including overloads) from ClassB, but the using directive cannot unhide ClassB::foo() in the context of ClassC, as that would produce an immediate name clash in the form of an illegal overload / an attempt for a member re-declaration at the first instantiation of the class, and not as late as trying to resolve member overloads at invocations. Essentially, bringing ClassB::foo() over to ClassC would've been analogous to:

[cpp]struct ClassC { template < typename A_T > void foo(A_T); template < typename B_T > void foo(B_T); }; [/cpp] This is not what the reported error says, though, as far as I can tell.

0 Kudos
Martin_K_6
Beginner
410 Views
Just a follow up, as last night I had no access to the ISO standard text, whereas I do now. I think the observed behavior of ICPC is in direct conflict with the 14882:2003 ISO standard:
7.3.3-12: When a using-declaration brings names from a base class into a derived class scope, member functions in the derived class override and/or hide member functions with the same name and parameter types in a base class (rather than conflicting).
So clearly ClassB::foo() should not have been considered for unhiding in the context of ClassC, since if it was unhidden it would have conflicted as described in my previous post, and the standard takes deliberate care of that.
0 Kudos
Judith_W_Intel
Employee
410 Views

 

The wording above mentions member functions but not member function templates. In the c++11 standard the wording was changed to include member function templates so I agree we should accept the code in -std=c++11 mode. This is the new C++11 wording:

p15 (C++11) When a using-declaration brings names from a base class into a derived class scope, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting).

Judy

0 Kudos
Reply