Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Overloaded operators and enums

Status
Not open for further replies.

amanison

Programmer
May 19, 2005
2
US
Can anyone explain what is happening here? I am trying to create overloaded relational operators for class member enums. VC6.0 and gcc 3.3.4 compile the code fine. VC7.0 and 7.1 complain that the overloaded operator function is ambiguous. The following code illustrates the problem:

Code:
class A
{
public:
  enum level
  {
    none, low, medium, high
  };
};

bool operator>( A::level l1, A::level l2 )
{
  bool greater = false;

  switch( l1 )
  {
  case A::low:
    switch( l2 )
    {
    case A::none: greater = true; break;
    }
    break;
  case A::medium:
    switch( l2 )
    {
    case A::low:
    case A::none: greater = true; break;
    }
    break;
  case A::high:
    switch( l2 )
    {
    case A::medium:
    case A::low:
    case A::none: greater = true; break;
    }
    break;
  }
  return greater;
}

int
main( int argc, char * argv[] )
{
  A::level l1 = A::high;
  A::level l2 = A::low;

  if( l1 < l2 )
  {
    return 1;
  }
  if( l1 > l2 )
  {
    return -1;
  }
  return 0;
}

VC6.0 and gcc compile cleanly. VC7.0 and 7.1 fail with the following error:

Compiling...
enumtest.cpp
d:\misc\test.cpp(54) : error C2593: 'operator >' is ambiguous
d:\misc\test.cpp(13): could be 'bool operator >(A::level,A::level)'
or 'built-in C++ operator>(A::level, A::level)'
while trying to match the argument list '(A::level, A::level)'

What are the built-in operators mentioned? Is the compiler assuming that an enum-is-an-enum-is-an enum, and thus bypasses the strong typing? What is the correct way to write this that conforms to the standard and is portable?

Any and all insights will be welcome.
 
Is there some reason you aren't using the default comparison for enums? The enumerated type generally assigns integral values to each enumerator, and so normal integer comparison can be used between members of the same enum. In your case your greater function just duplicates the natural integer ordering, so I'm not sure why it is necessary at all.

By the way, in a quick search through the standard I didn't notice any language that indicates which compiler is correct.
 
In the context of the above code, this question makes sense, but the code I posted was the distillation of the problem from a much larger application. That application is CORBA-based, and the specific problem that prompted my question arose from the mapping of CORBA IDL enumerations to C++. While C and C++ make certain guarantees about enums, CORBA does not, and it seems unwise to make assumptions about how CORBA enums are mapped to C++. Because of that I wanted to have relational operators that relied only upon equality/inequality, and let me code the relative values.

There are many possible workarounds, but I really would like to know if enums are supposed to be so weakly typed as the VC7.0 behaviour would imply. I ran some further tests to explore this. For example, adding
Code:
   int i = l1;
compiles cleanly on all compilers, but
Code:
   l2 = i;
generates the following error on all:
d:\misc\test.cpp(50) : error C2440: '=' : cannot convert from 'int' to 'A::level'
Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)

The difference appears to be that VC6.0 and gcc don't apply an integral promotion before looking for a matching function, while VC7.0 and 7.1 do. According to my reading of the standard this is not correct. "Each enumeration defines an integral type that is different from all other integral types" [r.7.1] and "Enumerations ... are distinct types and can be used to distinguish overloaded functions" [r.13.1]. This wording has been the language specification since 1991 at least. I am curious as to why Microsoft broke this behaviour in VC7.0, or if there is a switch to disable the built-in operators that conflict with the overloaded one.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top