关于在执行不合格调用时使用名称与使用命名空间的歧义

发布于 2025-01-18 04:26:18 字数 855 浏览 5 评论 0 原文

我知道这会是不明确的,

#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 ,情况并非如此。

这是为什么?

I knew that this would be ambiguous

#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);
}

because there's an equal both in boost::hana and ranges namespaces.

However, I thought this would be ambiguous too:

#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);
}

But that's not the case, according to GCC and Clang.

Why is that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

对你的占有欲 2025-01-25 04:26:18

摘要2

让我们查看示例中的第二个摘要的工作原理,因为您已经知道为什么第一个摘要会产生模棱两可的错误的原因。

来自使用指令的文档::

仅在命名空间范围和块范围中允许使用领域。从 不合格的名称查找使用方向性之后,直到出现的范围结束, namespace-name中的每个名称都可以看到在最近的封闭名称空间中声明,其中包含使用指导和名称空间名称。

使用指示性不会向其出现的声明区域添加任何名称(与使用删除不同),因此不会阻止相同的名称被声明。

这意味着使用指令的不在声明区域中引入名称(示例中 main 函数无非),而是转到最近的封闭式名称空间(哪个是示例中的全局名称空间)。

现在,当不合格的查找发生对呼叫表达式均等(v,v); 从遇到呼叫表达式的点上向上,并找到相等的版本是根据使用声明区域中的声明引入的( main ),因此搜索停止。因此,使用此版本已被使用。

一个人为的例子可能有助于澄清情况:

#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;
}

demo


snippet 1

snippet 1 smippet 1在示例中也可以根据示例中的示例来理解上面引用的陈述。特别是,您在摘要1中遇到模棱两可的错误,因为两个命名空间范围 boost :: hana 具有称为 quode>等于的函数同样排名。因此,当不合格的名称查找发生在 call expression quare(v,v)遇到表达式,并找到名为均等的函数,由于两个名称空间,它们在全局名称中可见。此外,由于两者都同样排名,因此我们会得到上述模棱两可的错误。

一个人为的例子可能有助于澄清情况:

#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;
}

demo

Snippet 2

Lets look at how the second snippet in your example works since you already know the reason for why the first snippet produces ambiguous error.

From Using directives' documentation:

Using-directives are allowed only in namespace scope and in block scope. From the point of view of unqualified name lookup of any name after a using-directive and until the end of the scope in which it appears, every name from namespace-name is visible as if it were declared in the nearest enclosing namespace which contains both the using-directive and namespace-name.

Using-directive does not add any names to the declarative region in which it appears (unlike the using-declaration), and thus does not prevent identical names from being declared.

This means that a using directive does not introduce name in the declarative region (which is nothing but the main function in your example), but instead to the nearest enclosing namespace( which is the global namespace in your example).

Now, when unqualified lookup happens for the call expression equal(v, v); the search goes upwards from the point where the call expression was encountered and it finds the equal version that was introduced due to the using declaration in the declarative region(which is main) and hence the search stops. And so this already found version is used.

A contrived example might help clarify the situation:

#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;
}

Demo


Snippet 1

Snippet 1 in your example can also be understood based upon the quoted statement above. In particular, you're getting ambiguous error in snippet 1 because both the namespaces ranges and boost::hana have a function called equal that are equally ranked. So when the unqualified name lookup happens for the call expression equal(v,v) the search starts and goes upwards from the point where the call expression was encountered and finds functions named equal that were made visible in the global namescope due to both of the namespaces. Moreover, since both are equally ranked, we get the mentioned ambiguous error.

A contrived example might help clarify the situation:

#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;
}

Demo

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文