c++/8875: Ambiguities in mixed template hierarchies

pawig@hildesheim.sgh-net.de pawig@hildesheim.sgh-net.de
Sun Dec 8 10:56:00 GMT 2002


>Number:         8875
>Category:       c++
>Synopsis:       Ambiguities in mixed template hierarchies
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          rejects-legal
>Submitter-Id:   net
>Arrival-Date:   Sun Dec 08 10:56:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Stefan Große Pawig
>Release:        gcc (GCC) 3.2.1 (also with 3.2)
>Organization:
>Environment:
Linux rigel 2.4.18 #5 Thu Aug 1 22:19:10 CEST 2002 i686 unknown
>Description:
The following code snippet (see below) exercises a base class
template with concrete and pure virtual methods as well as
general and specialized derived templates, which provide
implementations for the pure virtual methods.

Spezializations are provided for void* as well as for pointers
in general, which builds on the void* spezialization via
private inheritance.

The problem occurs when one of the concrete methods of the base
class is called on an instantiation of the derived template for
pointers (Derviced<int*> in the sample code): the compiler
complains that the concrete member is ambiguous (line 37).

Using explicit qualification works for Base<int*>::doThat() but
fails for Base<void*>::doThat() as expected (line 39), so
why does the compiler regard the unqualified call as ambiguous?

Am I missing something here? Or is this an effect of the
"Two stage lookup in templates is not implemented." as stated
on the "GCC Bugs" page?
>How-To-Repeat:
pawig@rigel:~/src > cat ctest1.cc
// Base class template
template <typename T>
class Base
{
public:
  virtual T doThis() const = 0;
  bool doThat() const { return doThis() == T(); }
};

// General Derived class template
template <typename T>
class Derived : public Base<T>
{
public:
  T doThis() const { return T(); }
};

// Derived specialized for void* 
template<>
class Derived<void*> : public Base<void*>
{
public:
  void* doThis() const { return reinterpret_cast<void*>(0x0badbeef); }
};

// Derived specialized for any pointer
template <typename T>
class Derived<T*> : public Base<T*>, private Derived<void*>
{
public:
  T* doThis() const { return static_cast<T*>(Derived<void*>::doThis()); }
};

int main()
{
  Derived<int*> d;
  bool b1 = d.doThat();                // Line 37
  bool b2 = d.Base<int*>::doThat();
  bool b3 = d.Base<void*>::doThat();   // Line 39
  return 0;
}
pawig@rigel:~/src > g++ -c ctest1.cc
ctest1.cc: In function `int main()':
ctest1.cc:37: request for member `doThat' is ambiguous
ctest1.cc:7: candidates are: bool Base<T>::doThat() const [with T = void*]
ctest1.cc:7:                 bool Base<T>::doThat() const [with T = int*]
ctest1.cc:39: `Base<void*>' is an inaccessible base of `Derived<int*>'
>Fix:
Workaround:
Instead of deriving Derived<T*> privately from Derived<void*>,
just put a Derived<void*> data meber into the Derived<T*> template. 
>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the Gcc-prs mailing list