The problem is that your class has a conversion operator to uint32_t
, so the compiler does not know whether to:
- Construct a
std::string
from the string literal and invoke your overload accepting an std::string
;
- Convert your
Foo
object into an uint32_t
and use it as an index into the string literal.
While option 2 may sound confusing, consider that the following expression is legal in C++:
1["foo"];
This is because of how the built-in subscript operator is defined. Per Paragraph 8.3.4/6 of the C++11 Standard:
Except where it has been declared for a class (13.5.5), the subscript operator [] is interpreted in such
a way that E1[E2]
is identical to *((E1)+(E2))
. Because of the conversion rules that apply to +, if E1
is an
array and E2
an integer, then E1[E2]
refers to the E2
-th member of E1
. Therefore, despite its asymmetric
appearance, subscripting is a commutative operation.
Therefore, the above expression 1["foo"]
is equivalent to "foo"[1]
, which evaluates to o
. To resolve the ambiguity, you can either make the conversion operator explicit
(in C++11):
struct Foo
{
explicit operator uint32_t() { /* ... */ }
// ^^^^^^^^
};
Or you can leave that conversion operator as it is, and construct the std::string
object explicitly:
f[std::string("foo")];
// ^^^^^^^^^^^^ ^
Alternatively, you can add a further overload of the subscript operator that accepts a const char*
, which would be a better match than any of the above (since it requires no user-defined conversion):
struct Foo
{
operator uint32_t() { /* ... */ }
Foo& operator[](const std::string &foo) { /* ... */ }
Foo& operator[](size_t index) { /* ... */ }
Foo& operator[](const char* foo) { /* ... */ }
// ^^^^^^^^^^^
};
Also notice, that your functions have a non-void return type, but currently miss a return
statement. This injects Undefined Behavior in your program.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…