Microsoft KB Archive/116239

= BUG: Function that Inherits Through Dominance Fails =

PSS ID Number: 116239

Article Last Modified on 10/16/2002

-

The information in this article applies to:

 Microsoft C/C++ Compiler (CL.EXE), when used with:  Microsoft C/C++ for MS-DOS

 Microsoft Visual C++ 1.0

 Microsoft Visual C++ 1.5

 Microsoft Visual C++, 32-bit Editions 1.0</li></ul>

 Microsoft Visual C++, 32-bit Editions 2.0</li></ul>

 Microsoft Visual C++, 32-bit Editions 4.0</li></ul>

 Microsoft Visual C++, 32-bit Editions 4.1</li></ul>

 Microsoft Visual C++, 32-bit Enterprise Edition 4.2</li></ul>

 Microsoft Visual C++, 32-bit Enterprise Edition 5.0</li></ul>

 Microsoft Visual C++, 32-bit Enterprise Edition 6.0</li></ul>

 Microsoft Visual C++, 32-bit Professional Edition 4.2</li></ul>

 Microsoft Visual C++, 32-bit Professional Edition 5.0</li></ul>

<ul> <li>Microsoft Visual C++, 32-bit Professional Edition 6.0</li></ul>

<ul> <li>Microsoft Visual C++, 32-bit Learning Edition 6.0</li></ul>

<ul> <li>Microsoft Visual C++ .NET (2002)</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q116239

<div class="symptoms_section">

SYMPTOMS
Code that makes use of the C++ implicit invocation of a user-defined conversion causes the C/C++ compiler to generate the following error message:

error C2594: '=' : ambiguous conversions from 'class ::E ' to 'int '

C/C++ 9.00 gives the following level 2 warning and errors from the implicit cast and only the warning from the explicit call:

warning C4250: 'E' : inherits 'B::operator`int'' via dominance error C2679: binary '=' : no operator defined which takes a right- hand operand of type 'class E' (or there is no acceptable conversion)

error C2594: '=' : ambiguous conversions from 'class E' to 'int'

NOTE: In Visual Studio .NET, the error message is:

warning C4250: 'E' : inherits 'B::B::operator`int'' via dominance. error C2679: binary '=' : no operator found which takes a right-hand operand of type 'E' (or there is no acceptable conversion)

<div class="resolution_section">

RESOLUTION
Explicitly invoke the user-defined conversion, as demonstrated in the sample code in the &quot;MORE INFORMATION&quot; section below, rather then depending on the implicit invocation.

<div class="status_section">

STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

<div class="moreinformation_section">

MORE INFORMATION
Suppose a virtual-base class A is defined and classes B and C inherit from class A. Furthermore, a class E inherits from both B and C. The two classes, A and B, each provide a virtual user-defined conversion function to &quot;int&quot;. The relationship may be represented by the following directed acyclic graph: <pre class="fixed_text">                        A int  } ^     ^                         /        \                         /          \                   B { int  }    C {} ^          ^                         \        /                           \      /                            E { } The dominance rule requires that when you invoke the virtual user-defined conversion function to int from an instance of an object of type E, the version provided by B should be used. This conversion function may be invoked implicitly by assigning an instance of an object of type E to an int. It may also be invoked explicitly through the use of the &quot;operator int&quot; function.

As demonstrated by the following sample code, the compiler accurately identifies and invokes the correct user-defined conversion function when using the explicit call syntax. However, when attempting to make use of the implicit conversion, the compiler produces an error, citing an ambiguity in its search for the correct user-defined conversion function.

Sample Code
/* Compile options needed: /W3
 * 1) include <iostream.h>
 * 1) include <iostream.h>

class A { public: virtual operator int { return 2; } };

class B : virtual public A { public: virtual operator int { return 3; } };

class C : virtual public A {};

class E : public B, public C {};

void main(void) {  int i;   int error=0;

E eObject;

// Both of the invocations below should call B's  // operator int.

if ((i = eObject) != 3)               // Fails to compile error = 1;

if ((i = eObject.operator int) != 3) // Compiles OK     error = 1;

if (!error) cout << &quot;PASSED&quot; << endl; else cout << &quot;FAILED&quot; << endl; }

<div class="references_section">