Pitfalls of C++’s subscript operator
What’s wrong with this C++ code?
#include <iostream> #include <string>
class Foo { public: Foo() { }
operator bool() { return true; }
std::string operator[](const std::string& s) { return s; } };
int main(void) { Foo foo; std::cout << foo["hello world!"] << std::endl; return 0; }
Answer:
Trying to compile the above code with gcc produces the following error:
In function `int main()': ambiguous overload for `Foo &[const char[13]]' candidates are: operator [](int, const char *) <builtin> class string Foo::operator [](const string &)
Wha—? Where the heck did operator[](int, const char*)
come from?
This little bit of goofiness is inherited from C. In C, the subscript operator is unintuitively commutative. That is, ptr[index]
is exactly the same as index[ptr]
!
In C, this is never a problem. Nobody writes code like index[ptr]
, and you can be blissfully ignorant that it’s allowed at all.
In C++, it can manifest itself where you don’t expect it, and this is what happens in the code above.
The compiler tries to parse the expression foo["hello world!"]
. Foo
doesn’t have an operator[](const char*)
method (nor an operator[](const char[13])
one), so the compiler has two choices:
- It can coerce
"hello world!"
to astd::string
and callFoo::operator[](const std::string&)
. - Since
Foo
hasoperator bool()
defined, the compiler can castfoo
to abool
. Now the expression involves abool
(an integer type) and a string literal (a character array), and because the subscript operator is commutative for this situation, it is legal to use thebool
as an index into"hello world!"
.
Each choice involves one cast, so the compiler considers both equally valid and can’t decide.
To fix this, we can add Foo::operator[](const char*)
and make the const char*
to std::string
coercion explicit:
class Foo { public: // ...
std::string operator[](const char* s) { return operator[](std::string(s)); } }
1 Comment »
RSS feed for comments on this post.
hard core. i miss programming. i get further and further away from this crap each year.
— ben @ October 22, 2006, 6:13 pm (PT)