提问人:Enlico 提问时间:3/31/2022 最后编辑:Enlico 更新时间:4/7/2022 访问量:243
关于执行非限定调用时使用名称与使用命名空间的歧义
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);
}
因为有一个 in 和 namespaces。equal
boost::hana
ranges
但是,我认为这也是模棱两可的:
#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
让我们看看示例中的第二个代码段是如何工作的,因为您已经知道第一个代码段产生歧义错误的原因。
从 Using 指令的文档:
Using指令只允许在命名空间作用域和块作用域中使用。从在 using 指令之后的任何名称的非限定名称查找的角度来看,直到它出现的范围结束,namespace-name 中的每个名称都是可见的,就好像它是在最近的封闭命名空间中声明的一样,该命名空间同时包含 using 指令和 namespace-name。
using-directive 不会向它所在的声明性区域添加任何名称(与 using-declaration 不同),因此不会阻止声明相同的名称。
这意味着 a 不会在声明性区域(只不过是示例中的函数)中引入名称,而是引入最近的封闭命名空间(在示例中是 )。using directive
main
global namespace
现在,当对调用表达式进行非限定查找时,搜索会从遇到调用表达式的点向上移动,并找到由于声明性区域(即 )而引入的版本,因此搜索停止。所以这个已经找到的版本被使用了。equal(v, v);
equal
using declaration
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;
}
片段 1
您示例中的片段 1 也可以根据上面引用的语句来理解。特别是,您在代码片段 1 中出现不明确错误,因为命名空间和具有调用的函数的排名相同。因此,当对调用表达式进行非限定名称查找时,搜索将从遇到调用表达式的点开始并向上移动,并查找由于这两个命名空间而在全局命名范围内可见的命名函数。此外,由于两者的排名相等,我们得到了上述模棱两可的错误。ranges
boost::hana
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;
}
评论