为什么一个程序被拒绝为可以通过过载解决来解决的模糊程序

Why is a program rejected as ambiguous that could be resolved by overload resolution?

本文关键字:程序 解决 可以通过 模糊 拒绝 一个 为什么      更新时间:2023-10-16

以下程序因不明确而被gcc拒绝:

struct Aint 
{
    virtual void foo(int);
};
struct Astring 
{
    virtual void foo(std::string);
};
struct A: public Aint, public Astring {};
int main()
{
  std::string s;
  A a;
  a.foo(s);
  return 0; 
}
> vt.cpp: In function ‘int main()’: vt.cpp:13:9: error: request for
> member ‘foo’ is ambiguous
>        a.foo(s);
>          ^ vt.cpp:5:34: note: candidates are: virtual void Astring::foo(std::__cxx11::string)
>      struct Astring {virtual void foo(std::string);};
>                                   ^ vt.cpp:4:31: note:                 virtual void Aint::foo(int)
>      struct Aint {virtual void foo(int);};

Clang一直以同样的理由拒绝该程序:

clang -std=c++1y -c vt.cpp 
vt.cpp:13:9: error: member 'foo' found in multiple base classes of different types
      a.foo(s);
        ^
vt.cpp:4:31: note: member found by ambiguous name lookup
    struct Aint {virtual void foo(int);};
                              ^
vt.cpp:5:34: note: member found by ambiguous name lookup
    struct Astring {virtual void foo(std::string);};

我不完全确定我是否正确理解了第10.2节中的查找规则,所以我将通过以下步骤中的规则来计算查找集S(foo,A):

1. A does not contain `foo`, so rule 5 applies and S(foo, A) is initially empty. We need to calculate the lookup sets S(foo, Aint) and S(foo, Afloat) and merge them to S(foo, A) = {}
2. S(foo, Aint) = {Aint::foo}
3. S(foo, Afloat) = {Afloat::foo}
4. Merge S(foo, Aint) = {Aint::foo} into S(foo, A) = {} to get S(foo, A) = {Aint::foo} (second case of 6.1)
5. Merge S(foo, Afloat) = {Afloat::foo} into {Aint::foo}. This create an ambiguous lookup set because of rule 6.2

结果集是一个无效集,因此程序格式不正确。

我想知道为什么这个项目这么早就被拒绝了。在这种情况下,编译器应该很容易进行重载解析,因为两个函数的名称相同,但签名不同,所以没有真正的歧义。是否有技术原因没有这样做,或者是否有其他原因会接受不正确的程序?有人知道这么早就拒绝这些项目的决定背后的理性吗?

在C++中,不存在跨作用域的重载——派生类作用域不是这个一般规则的例外。请参阅以了解更多详细信息。无论如何,您的示例可以通过指定您希望通过"using"关键字同时使用两个版本的foo来进行改进。请参阅以下示例。

示例程序:

#include <iostream>
#include <string>
struct Aint 
{
     void foo(int){std::cout<<"n Aint";}
};
struct Astring 
{
     void foo(std::string){std::cout<<"n Astring";}
};
struct A: public Aint, public Astring {
    using Aint::foo;
    using Astring::foo;
    };
int main()
{
  std::string s;
  A a;
 a.foo(s);
  return 0; 
}
output:Astring
相关文章: