簡體   English   中英

關於在進行不合格調用時使用名稱與使用命名空間的歧義

[英]About the ambiguity of using a name vs using a namespace when doing unqualified calls

我知道這會模棱兩可

#include <boost/hana/fwd/equal.hpp>
#include <range/v3/algorithm/equal.hpp>
#include <vector>

int main() {
    std::vector<int> v{1,2,3};
    using namespace boost::hana;
    using namespace ranges;
    equal(v, v);
}

因為boost::hanaranges命名空間是equal的。

但是,我認為這也很模棱兩可:

#include <boost/hana/fwd/equal.hpp>
#include <range/v3/algorithm/equal.hpp>
#include <vector>

int main() {
    std::vector<int> v{1,2,3};
    using namespace boost::hana;
    using ranges::equal;
    equal(v, v);
}

但根據GCC 和 Clang ,情況並非如此。

這是為什么?

片段 2

讓我們看看示例中的第二個代碼段是如何工作的,因為您已經知道第一個代碼段產生不明確錯誤的原因。

來自使用指令的文檔

僅在命名空間 scope 和塊 scope 中允許使用指令。從使用指令之后的任何名稱的非限定名稱查找的角度來看,直到它出現的 scope 結束,命名空間名稱中的每個名稱都是可見,就好像它是在最近的包含 using-directive 和 namespace-name 的封閉命名空間中聲明的一樣

using-directive 不會將任何名稱添加到它出現的聲明區域(與 using-declaration 不同),因此不會阻止聲明相同的名稱。

這意味着using directive不會在聲明區域中引入名稱(在您的示例中它只是main的 function),而是引入最近的封閉命名空間(在您的示例中是global namespace )。

現在,當調用表達式equal(v, v);發生非限定查找時 搜索從遇到調用表達式的點向上進行,並找到由於聲明區域(即main )中的using declaration而引入的equal版本,因此搜索停止。 所以這個已經找到的版本被使用。

一個人為的例子可能有助於澄清情況:

#include <iostream>
namespace X 
{
    void func(){std::cout<<"X version called"<<std::endl;}
}
namespace Y 
{
    void func(){std::cout<<"Y version called"<<std::endl;};
}
int main()
{
    using namespace X;
    using Y::func;
    
    func(); //calls Y version
    return 0;
}

演示


片段 1

您的示例中的代碼段 1 也可以根據上面引用的語句來理解。 特別是,您在片段 1 中遇到了不明確的錯誤,因為命名空間rangesboost::hana都有一個 function 被稱為equal ,它們的排名相同 因此,當調用表達式equal(v,v)發生非限定名稱查找時,搜索開始並從遇到調用表達式的點向上查找,並找到名為equal的函數,由於這兩個原因,它們在全局名稱范圍中可見名稱空間。 此外,由於兩者排名相同,我們得到了提到的模棱兩可的錯誤。

一個人為的例子可能有助於澄清情況:

#include <iostream>
namespace X 
{
    void func(int)
    {
        std::cout<<"X version func called"<<std::endl;
    }
    
    void foo()
    {
        std::cout<<"X version foo called"<<std::endl;
    }
}
namespace Y 
{
    void func(double)
    {
        std::cout<<"Y version func called"<<std::endl;
    }
    void foo()
    {
        std::cout<<"Y version foo called"<<std::endl;
    }
}
int main()
{
    using namespace X ;
    using namespace Y;
    
    func(3); //calls X's func 
    func(5.5);//calls Y's func
    
    foo();//fails due to ambiguity
    return 0;
}

演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM