这段代码如何导致NS1 :: format和NS3 :: format之间的歧义?

时间:2016-10-07 08:48:56

标签: c++ namespaces

是否导入了格式,因为它使用的是导入的Object类? 但是使用相同的逻辑,如果使用导入的Object类,则不会导入类。

namespace NS1  {
    class Object { /* ... */ };
    int format(const Object&) { std::cout << "NS1"; }
    namespace NS2  {
        class Object { /* ... */ };
        int format(const Object&) { std::cout << "NS2"; }
    }
}

namespace NS3  {
    using NS1::Object;
    int format(const Object&) { std::cout << "NS3"; }
}

namespace  {  using namespace NS3;  }

void fun(Object b, int i)  {  int i1 = format(b);  }

int main()  {
    Object b;
    fun(b, 0);
}

1 个答案:

答案 0 :(得分:0)

让我们看一下GCC产生的错误信息:

test.cpp: In function ‘void fun(NS1::Object, int)’:
test.cpp:19:48: error: call of overloaded ‘format(NS1::Object&)’ is ambiguous
 void fun(Object b, int i)  {  int i1 = format(b);  }
                                                ^
test.cpp:19:48: note: candidates are:
test.cpp:14:5: note: int NS3::format(const NS1::Object&)
 int format(const Object&) { std::cout << "NS3"; }
     ^
test.cpp:5:5: note: int NS1::format(const NS1::Object&)
 int format(const Object&) { std::cout << "NS1"; }
     ^

出现歧义的原因是argument-dependent lookup

  

依赖于参数的查找(也称为ADL或Koenig查找)是用于在函数调用表达式中查找非限定函数名称的规则集,包括对重载运算符的隐式函数调用。 除了通常的非限定名称查找所考虑的范围和名称空间外,还会在参数的名称空间中查找这些函数名称。

在您的情况下,您正试图致电format(b),其中bNS1::Object

  • 考虑函数int NS3::format(const NS1::Object&)是因为您拉入了该命名空间。
  • 因为ADL而考虑函数int NS1::format(const NS1::Object&):参数来自名称空间NS1,因此也会考虑来自NS1的匹配函数。
  • 两个函数都具有完全相同的签名,因此不明确。

值得一读What is "Argument-Dependent Lookup" (aka ADL, or "Koenig Lookup")?