命名空间对C++模板推导优先级的影响
Impact of namespaces on C++ template deduction priority
在尝试实现元功能时,只有当某些类型存在“abs”功能时才需要存在,我 运行 遇到以下问题:
这里有两个代码示例,我希望产生相同的结果,但实际上它们不会:
第一个例子
#include <iostream>
#include <cmath>
using namespace std;
struct Bar{};
template<typename T>
int abs(T& v)
{
return -1;
}
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
int main()
{
test();
}
产量:
2
-1
这是我所期望的
第二个例子
#include <iostream>
#include <cmath>
namespace Foo
{
struct Bar{};
using namespace std;
template<typename T>
int abs(T& v)
{
return -1;
}
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
}
int main()
{
Foo::test();
}
产量:
-1
-1
为什么在这里使用命名空间会使编译器优先于“本地”abs 方法 std::abs?
在第二种情况下,using 指令将声明的名称放置在全局名称空间中的指定名称空间中,以进行非限定名称查找。因此,在命名空间 Foo
中,找到了在此命名空间中声明的非限定名称 abs
。即在命名空间Foo
中声明的名称abs
隐藏了在全局命名空间中声明的名称abs
。
来自 C++ 14 标准(7.3.4 Using 指令)
2 A using-directive specifies that the names in the nominated
namespace can be used in the scope in which the using-directive
appears after the using-directive. During unqualified name lookup
(3.4.1), the names appear as if they were declared in the nearest
enclosing namespace which contains both the using-directive and the
nominated namespace. [ Note: In this context, “contains” means
“contains directly or indirectly”. — end note ]
第二个程序中最近的封闭命名空间是全局命名空间。
下面还有两个程序演示了使用 using 指令时非限定名称查找的相同原理。
#include <iostream>
void s() { std::cout << "The function s() called.\n"; }
struct s
{
s() { std::cout << "The constructor of struct s called.\n"; }
};
void test()
{
s();
}
int main()
{
test();
}
程序输出为
The function s() called.
在此演示程序中,函数 s
的声明隐藏了结构 s
的声明。
第二个节目。
#include <iostream>
namespace N1
{
void s() { std::cout << "The function N1::s() called.\n"; }
}
namespace N2
{
using namespace N1;
struct s
{
s() { std::cout << "The constructor of struct N2::s called.\n"; }
};
void test()
{
s();
}
}
int main()
{
N2::test();
}
程序输出为
The constructor of struct N2::s called.
在这种情况下,名称为 s
的结构声明隐藏了同名函数 s
,由于 using 指令,其声明被放置在全局命名空间中。
为什么会出现这种情况可以参考Vlad的回答。但是,如果您仍然希望能够执行测试,则可以在单独的命名空间中进行测试。
#include <iostream>
#include <cmath>
namespace Foo
{
template<typename T>
int abs(T& v)
{
return -1;
}
}
namespace Test
{
struct Bar{};
using namespace std;
using namespace Foo;
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
}
int main()
{
Test::test();
}
输出为
2
-1
在尝试实现元功能时,只有当某些类型存在“abs”功能时才需要存在,我 运行 遇到以下问题:
这里有两个代码示例,我希望产生相同的结果,但实际上它们不会:
第一个例子
#include <iostream>
#include <cmath>
using namespace std;
struct Bar{};
template<typename T>
int abs(T& v)
{
return -1;
}
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
int main()
{
test();
}
产量:
2
-1
这是我所期望的
第二个例子
#include <iostream>
#include <cmath>
namespace Foo
{
struct Bar{};
using namespace std;
template<typename T>
int abs(T& v)
{
return -1;
}
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
}
int main()
{
Foo::test();
}
产量:
-1
-1
为什么在这里使用命名空间会使编译器优先于“本地”abs 方法 std::abs?
在第二种情况下,using 指令将声明的名称放置在全局名称空间中的指定名称空间中,以进行非限定名称查找。因此,在命名空间 Foo
中,找到了在此命名空间中声明的非限定名称 abs
。即在命名空间Foo
中声明的名称abs
隐藏了在全局命名空间中声明的名称abs
。
来自 C++ 14 标准(7.3.4 Using 指令)
2 A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. [ Note: In this context, “contains” means “contains directly or indirectly”. — end note ]
第二个程序中最近的封闭命名空间是全局命名空间。
下面还有两个程序演示了使用 using 指令时非限定名称查找的相同原理。
#include <iostream>
void s() { std::cout << "The function s() called.\n"; }
struct s
{
s() { std::cout << "The constructor of struct s called.\n"; }
};
void test()
{
s();
}
int main()
{
test();
}
程序输出为
The function s() called.
在此演示程序中,函数 s
的声明隐藏了结构 s
的声明。
第二个节目。
#include <iostream>
namespace N1
{
void s() { std::cout << "The function N1::s() called.\n"; }
}
namespace N2
{
using namespace N1;
struct s
{
s() { std::cout << "The constructor of struct N2::s called.\n"; }
};
void test()
{
s();
}
}
int main()
{
N2::test();
}
程序输出为
The constructor of struct N2::s called.
在这种情况下,名称为 s
的结构声明隐藏了同名函数 s
,由于 using 指令,其声明被放置在全局命名空间中。
为什么会出现这种情况可以参考Vlad的回答。但是,如果您仍然希望能够执行测试,则可以在单独的命名空间中进行测试。
#include <iostream>
#include <cmath>
namespace Foo
{
template<typename T>
int abs(T& v)
{
return -1;
}
}
namespace Test
{
struct Bar{};
using namespace std;
using namespace Foo;
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
}
int main()
{
Test::test();
}
输出为
2
-1