error: ambiguous overload for ‘operator[]’

huangapple go评论99阅读模式
英文:

error: ambiguous overload for 'operator[]'

问题

  1. 为什么添加一个带有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,所以编译器无法确定应该选择哪个重载,从而导致二义性。

  2. 为什么问题只出现在索引为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
>

  1. Why adding an overload with a std::string parameter make the foo[0] ambiguous ?
  2. And why the problem is only with the index 0 ?

答案1

得分: 6

问题在于构造函数std::string::string(const char*)不是显式的(而0是一个空指针常量),这意味着重载Foo::Foo operator[](int) constFoo::Foo operator[](const std::string&)都是可行的,但排名相同。这反过来意味着调用是模糊的,因为它们中没有一个比另一个更好。

特别是,Foo::Foo operator[](int) const对其第一个隐式参数需要转换,但对其第二个int参数不需要转换。另一方面,Foo::Foo operator[](const std::string&)对其第一个隐式参数不需要转换,但需要使用构造函数std::string::string(const char*)0std::string进行隐式转换。由于这两个重载都不比另一个更好,因此调用是模糊的。


请注意,在重载Foo::Foo operator[](int) constFoo::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).

huangapple
  • 本文由 发表于 2023年3月3日 18:22:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75625845.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定