【问题标题】:Ambiguity between function and function in namespace with same argument具有相同参数的命名空间中的函数和函数之间的歧义
【发布时间】:2021-05-05 08:13:42
【问题描述】:

谁能解释为什么A::f(const B& b)f(const A::B& b) 之间存在歧义。我认为代码中的意图非常明确。

#include <iostream>

namespace A
{
  class B
  {
  protected:
    double value_;
  public:
    B() : value_(15.0) {}
    double getValue() const {return value_;}
  };

  void f(const B& b)
  {
    std::cout << "f(b) = " << b.getValue() << std::endl;
  }
}

void f(const A::B& b)
{
  std::cout << "Other f(b) = " << b.getValue() << std::endl;
}

int main()
{
  A::B b;
  A::f(b);
  f(b);
  return 0;
}

但是,g++ 7.5.0 和 clang 6.0.0 都抱怨函数调用不明确 (error: call of overloaded ‘f(A::B&amp;)’ is ambiguous) 无论编译器标志和优化如何。

【问题讨论】:

  • 又一天,ADL 的另一个受害者

标签: c++ namespaces function-call argument-dependent-lookup


【解决方案1】:

这是argument-dependent lookup 的示例。

即使 ::main 在全局命名空间中,A::f 也可以在不使用完全限定名称的情况下调用,因为它是在其参数 A::B 的命名空间 A 中查找的。因此,::fA::f 之间存在歧义。

要解决歧义,您需要致电A::f(b)(如您所做的那样)或::f(b)

【讨论】:

    【解决方案2】:

    对于这个函数调用表达式

    f(b);
    

    编译器找到在全局命名空间中声明的名称f。另一方面,使用参数相关查找,编译器还通过命名空间A 进行查找,其中声明了类B,并且还找到了名称为f 的函数。这两个函数都不是被调用的最佳候选者。所以有歧义。

    除了使用函数的限定名称来避免歧义之外,您还可以通过以下方式抑制参数依赖查找

    ( f )( b );
    

    依赖于参数的查找对于搜索友元函数非常有用,如果它们仅定义在授予友谊的类中,则它们不可见。

    这是一个演示程序

    #include <iostream>
    
    namespace N
    {
        
    
        class A
        {
        private:
            int x;
        
        public:
            A( int x ) : x( x ) {}
        
            friend std::ostream & operator <<( std::ostream &os, const A &a )
            {
                return os << a.x;
            }
        };
    }
    
    int main()
    {
    
        N::A a( 10 );
        
        std::cout << a << '\n';
        
        return 0;
    }
    

    程序输出是

    10
    

    如果参数依赖查找不存在,则无法调用朋友 operator &lt;&lt;,因为即使在命名空间 N 中也找不到它

    考虑以下程序。

    #include <iostream>
    
    namespace N
    {
        class A
        {
        private:
            int x;
        
        public:
            A( int x ) : x( x ) {}
        
            friend void f( int x )
            {
                A a( x );
                
                std::cout << a.x << '\n';
            }
        };
    }
    
    int main()
    {
        N::f( 10 );
        
        return 0;
    }
    

    即使指定限定名N::f,也无法调用友元函数f。对于这个程序,编译器将发出一个错误,指出‘f’ is not a member of ‘N’。要使函数可见,您还需要在 A 类之外声明它,例如

    #include <iostream>
    
    namespace N
    {
        class A
        {
        private:
            int x;
        
        public:
            A( int x ) : x( x ) {}
        
            friend void f( int x )
            {
                A a( x );
                
                std::cout << a.x << '\n';
            }
        };
        
        void f( int ); // make the function visible
    }
    
    int main()
    {
        N::f( 10 );
        
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多