4

Consider the following code:

class DictionaryRef {
public:    
  operator bool() const;
  std::string const& operator[](char const* name) const;

  // other stuff
};

int main() {
  DictionaryRef dict;
  char text[256] = "Hello World!";

  std::cout << dict[text] << std::endl;
}

This produces the following warning when compiled with G++:

warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
note: candidate 1: const string& DictionaryRef::operator[](const char*) const
note: candidate 2: operator[](long int, char*) <built-in>

I know what this means (and the cause is been explained in operator[](const char *) ambiguity) but I'm looking for a way to ensure correct behavior/resolve the warning without changing my class design - since it makes perfect sense for a class to have both a boolean conversion, and a [](const char*) operator.

What's the purpose of operator[](long int, char*) besides generating random compiler warnings? I can't imagine someone writing 1["hello"] in real code.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
riv
  • 6,846
  • 2
  • 34
  • 63
  • 1
    My guess would be that it's c legacy. In c, `array[index]` is just another notation for `*(array + index)`, so swapping `array` and `index` has no influence on the result (of course, even in c code that use is very rare). – Ben Steffan May 01 '17 at 19:36
  • 5
    `explicit operator bool() const` seems to solve the issue. – zett42 May 01 '17 at 19:40
  • 2
    Make the conversion to bool explicit. –  May 01 '17 at 19:40

1 Answers1

0

Although you "can't imagine someone writing 1["hello"] in a real code", this is something that's legal C++, as a consequence of the commutative [] inherited from C. Reasonable or not, that's how the language is defined, and it's unlikely to be changing for us.

The best way to avoid the ambiguity is to add explicit to the boolean conversion - it's very rare that we ever want a non-explicit operator bool().

An alternative is to replace operator bool() with an operator void*(), which will still satisfy boolean tests, but not convert to integer.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103