我正在尝试像类的[]运算符一样实现矢量和地图.但我收到编译器的错误消息(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,所以编译器不知道是否:
std::string从字符串文字构造一个并调用你的重载接受一个std::string;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)).由于适用于+的转换规则,ifE1是数组和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语句.这会在程序中注入未定义的行为.
| 归档时间: |
|
| 查看次数: |
2752 次 |
| 最近记录: |