"运算符[]'的模糊重载"如果存在转换运算符到int

r2p*_*2p2 14 c++

我正在尝试像类的[]运算符一样实现矢量和地图.但我收到编译器的错误消息(g ++和clang ++).发现只有当类还将转换运算符转换为整数类型时才会出现它们.

现在我有两个问题.首先是我不知道为什么编译器无法区分[](const std :: string&)以及类何时将转换运算符转换为int.第二个......我需要转换和索引运算符.有谁知道如何解决这个问题?

在此先感谢并向我致以最诚挚的问候

作品:

#include <stdint.h>
#include <string>

struct Foo
{
    Foo& operator[](const std::string &foo) {}
    Foo& operator[](size_t index) {}
};

int main()
{
    Foo f;
    f["foo"];
    f[2];
}
Run Code Online (Sandbox Code Playgroud)

不起作用:

#include <stdint.h>
#include <string>

struct Foo
{
    operator uint32_t() {}
    Foo& operator[](const std::string &foo) {}
    Foo& operator[](size_t index) {}
};

int main()
{
    Foo f;
    f["foo"];
    f[2];
}
Run Code Online (Sandbox Code Playgroud)

编译器错误:

main.cpp: In function 'int main()':
main.cpp:14:9: error: ambiguous overload for 'operator[]' in 'f["foo"]'
main.cpp:14:9: note: candidates are:
main.cpp:14:9: note: operator[](long int, const char*) <built-in>
main.cpp:7:7: note: Foo& Foo::operator[](const string&)
main.cpp:8:7: note: Foo& Foo::operator[](size_t) <near match>
main.cpp:8:7: note:   no known conversion for argument 1 from 'const char [4]' to 'size_t {aka long unsigned int}'
Run Code Online (Sandbox Code Playgroud)

And*_*owl 20

问题是你的类有一个转换运算符uint32_t,所以编译器不知道是否:

  1. std::string从字符串文字构造一个并调用你的重载接受一个std::string;
  2. 将您的Foo对象转换为a uint32_t并将其用作字符串文字的索引.

虽然选项2可能听起来令人困惑,但请考虑以下表达式在C++中是合法的:

1["foo"];
Run Code Online (Sandbox Code Playgroud)

这是因为定义了内置下标运算符.根据C++ 11标准的第8.3.4/6段:

除非已为类声明(13.5.5),否则下标运算符[]的解释方式与之E1[E2]相同*((E1)+(E2)).由于适用于+的转换规则,if E1是数组和E2整数,因此E1[E2]引用的是E2-th成员E1.因此,尽管外观不对称,但下标是一种可交换的操作.

因此,上面的表达式1["foo"]相当于"foo"[1],其评估结果为o.要解决歧义,您可以创建转换运算符explicit(在C++ 11中):

struct Foo
{
    explicit operator uint32_t() { /* ... */ }
//  ^^^^^^^^
};
Run Code Online (Sandbox Code Playgroud)

或者您可以保留该转换运算符,并std::string显式构造该对象:

    f[std::string("foo")];
//    ^^^^^^^^^^^^     ^
Run Code Online (Sandbox Code Playgroud)

或者,您可以添加接受a的下标运算符的进一步重载const char*,这将是比上述任何更好的匹配(因为它不需要用户定义的转换):

struct Foo
{
    operator uint32_t() { /* ... */ }
    Foo& operator[](const std::string &foo) { /* ... */ }
    Foo& operator[](size_t index) { /* ... */ }
    Foo& operator[](const char* foo) { /* ... */ }
    //              ^^^^^^^^^^^
};
Run Code Online (Sandbox Code Playgroud)

另请注意,您的函数具有非void返回类型,但目前错过了一个return语句.这会在程序中注入未定义的行为.