英文:
error: ambiguous overload for 'operator[]'
问题
-
为什么添加一个带有
std::string
参数的重载会使foo[0]
变得模糊不清?问题出现在这里是因为编译器在处理
foo[0]
时存在二义性。当你添加了一个接受std::string
参数的重载函数后,编译器不确定在foo[0]
中应该调用哪个重载函数:接受整数参数的Foo operator[](int index) const
还是接受std::string
参数的Foo operator[](std::string const& name) const
。因为整数0可以隐式转换为std::string
,所以编译器无法确定应该选择哪个重载,从而导致二义性。 -
为什么问题只出现在索引为0的情况下?
问题仅在索引为0的情况下出现,因为整数0可以被隐式转换为
std::string
,而对于其他非零整数索引,编译器可以准确定位到要调用的重载函数。所以,只有在索引为0时,编译器才会遇到二义性问题。
英文:
I have an error I don't understand.
The following snippet compiles
#include <iostream>
class Foo
{
std::string m_name;
public:
explicit Foo(std::string const& name):m_name{name}{}
Foo operator[](int index) const {std::cout<<"size_t const\n"; return Foo{m_name};}
Foo operator[](std::string const& name) const { std::cout<<"str const\n"; return Foo{name}; }
};
int main()
{
Foo foo{"Cool"};
foo[0];
foo[1];
return 0;
}
but the following doesn't not compile for index=0 when I overload the operator[](std::string const&)
#include <iostream>
class Foo
{
std::string m_name;
public:
explicit Foo(std::string const& name):m_name{name}{}
Foo operator[](int index) const {std::cout<<"size_t const\n"; return Foo{m_name};}
Foo operator[](std::string const& name) const { std::cout<<"str const\n"; return Foo{name}; }
Foo operator[](std::string const& name) { std::cout<<"str non const\n"; return Foo{name}; } //doesn't compile with
};
int main()
{
Foo foo{"Cool"};
foo[0]; //doesn't compile
foo[1]; //compile
return 0;
}
and in this case I have the following compile-error:
>none
>main.cpp: In function 'int main()':
>main.cpp:25:8: error: ambiguous overload for 'operator[]' (operand types are 'Foo' and 'int')
> 25 | foo[0]; //doesn't compile
>main.cpp:12:5: note: candidate: 'Foo Foo::operator[](int) const'
> 12 | Foo operator[](int index) const {std::cout<<"size_t const\n"; return Foo{m_name};}
>main.cpp:13:5: note: candidate: 'Foo Foo::operator[](const std::string&) const'
> 13 | Foo operator[](std::string const& name) const { std::cout<<"str const\n"; return Foo{name}; }
> main.cpp:14:5: note: candidate: 'Foo Foo::operator[](const std::string&)'
> 14 | Foo operator[](std::string const& name) { std::cout<<"str non const\n"; return Foo{name}; } //doesn't compile with
>
- Why adding an overload with a
std::string
parameter make thefoo[0]
ambiguous ? - And why the problem is only with the index 0 ?
答案1
得分: 6
问题在于构造函数std::string::string(const char*)
不是显式的(而0
是一个空指针常量),这意味着重载Foo::Foo operator[](int) const
和Foo::Foo operator[](const std::string&)
都是可行的,但排名相同。这反过来意味着调用是模糊的,因为它们中没有一个比另一个更好。
特别是,Foo::Foo operator[](int) const
对其第一个隐式参数需要转换,但对其第二个int
参数不需要转换。另一方面,Foo::Foo operator[](const std::string&)
对其第一个隐式参数不需要转换,但需要使用构造函数std::string::string(const char*)
从0
到std::string
进行隐式转换。由于这两个重载都不比另一个更好,因此调用是模糊的。
请注意,在重载Foo::Foo operator[](int) const
和Foo::Foo operator[](const std::string&) const
之间不会出现这个问题,因为在这种情况下前者比后者更匹配,因为它不需要对其第二个int
参数进行任何转换,而这两个重载都需要对其第一个隐式参数进行转换。
因此,一个简单(直接)的修复方法是添加一个非const版本的Foo::Foo operator[](int index)
。
英文:
The problem is that the constructor std::string::string(const char*)
is not explicit(and 0
is a null pointer constant) which means that the both the overloads Foo::Foo operator[](int) const
and Foo::Foo operator[](const std::string&)
are viable but have the same rank. This in turn means that the call is ambiguous since neither of them is better than the other.
In particular, Foo::Foo operator[](int) const
requires conversion for its first implicit parameter but no conversion for its second int
parameter. On the other hand, Foo::Foo operator[](const std::string&)
requires no conversion for its first implicit parameter but requires an implicit conversion from 0
to std::string
using the constructor std::string::string(const char*)
. And as neither of these overloads is better than the other, the call is ambiguous.
Note that this problem doesn't occur between the overloads Foo::Foo operator[](int) const
and Foo::Foo operator[](const std::string&) const
because in this case the former is a better match than the latter as it doesn't require any conversion for its second int
argument and both of these overloads requires a conversion for their first implicit parameter.
Thus one simple(straightforward) fix is to add a non-const overload Foo::Foo operator[](int index)
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论