查看名称空间的重载解决方案
Overload resolution looking into namespaces
以下代码按预期失败,因为未发现 get
的重载。使用 std::get
将解决问题。
#include <array>
int main()
{
std::array<int, 2> ar{2,3};
auto r = get<0>(ar);//fails, get was not declared in this scope
}
但是,引入模板化版本的 get
,即使它与函数调用不匹配,也会以某种方式使编译器使用 std::get
版本:
#include <array>
template <typename T>
void get(){};
int main()
{
std::array<int, 2> ar{2,3};
auto r = get<0>(ar);//returns 2
}
我找不到标准的任何部分对此进行解释。这是我测试的所有 3 个编译器中的错误(可能不是),还是我遗漏了什么?
此行为已在
中测试
- MSVC 15.9.2
- 叮当声 8.0.0
- GCC 9.0.0(仍是实验版)
编辑:
我知道 ADL。但是,如果 ADL 使第二个代码起作用,为什么它不能在第一部分中起作用?
除非在调用点引入模板函数声明,否则在涉及显式模板参数时不使用 ADL。您正在使用非类型模板参数 0
使用 get
的非限定形式,因此您需要引入模板函数声明或使用 get
的限定版本作为 std::get<0>(ar)
.
标准语[temp.arg.explicit]/8
:(强调我的)
[ Note: For simple function names, argument dependent lookup (6.4.2) applies even when the function name is not visible within the scope of the call. This is because the call still has the syntactic form of a function call (6.4.1). But when a function template with explicit template arguments is used, the call does not have the correct syntactic form unless there is a function template with that name visible at the point of the call. If no such name is visible, the call is not syntactically well-formed and argument-dependent lookup does not apply. If some such name is visible, argument dependent lookup applies and additional function templates may be found in other namespaces.
编辑:
正如@Yakk - Adam Nevraumont 在评论中指出的那样,如果不存在模板函数声明,表达式 get<0>(ar)
将被解析为 (get<0)>(ar)
,即作为一系列比较表达式而不是函数调用。
请注意,由于 P0846R0,这在 C++20 中发生了变化。一个非限定名称后跟一个 <
标记,普通的非限定查找找到一个或多个函数或什么也找不到,现在假定为命名模板,并且 <
被相应地解析。
以下代码按预期失败,因为未发现 get
的重载。使用 std::get
将解决问题。
#include <array>
int main()
{
std::array<int, 2> ar{2,3};
auto r = get<0>(ar);//fails, get was not declared in this scope
}
但是,引入模板化版本的 get
,即使它与函数调用不匹配,也会以某种方式使编译器使用 std::get
版本:
#include <array>
template <typename T>
void get(){};
int main()
{
std::array<int, 2> ar{2,3};
auto r = get<0>(ar);//returns 2
}
我找不到标准的任何部分对此进行解释。这是我测试的所有 3 个编译器中的错误(可能不是),还是我遗漏了什么?
此行为已在
中测试- MSVC 15.9.2
- 叮当声 8.0.0
- GCC 9.0.0(仍是实验版)
编辑: 我知道 ADL。但是,如果 ADL 使第二个代码起作用,为什么它不能在第一部分中起作用?
除非在调用点引入模板函数声明,否则在涉及显式模板参数时不使用 ADL。您正在使用非类型模板参数 0
使用 get
的非限定形式,因此您需要引入模板函数声明或使用 get
的限定版本作为 std::get<0>(ar)
.
标准语[temp.arg.explicit]/8
:(强调我的)
[ Note: For simple function names, argument dependent lookup (6.4.2) applies even when the function name is not visible within the scope of the call. This is because the call still has the syntactic form of a function call (6.4.1). But when a function template with explicit template arguments is used, the call does not have the correct syntactic form unless there is a function template with that name visible at the point of the call. If no such name is visible, the call is not syntactically well-formed and argument-dependent lookup does not apply. If some such name is visible, argument dependent lookup applies and additional function templates may be found in other namespaces.
编辑:
正如@Yakk - Adam Nevraumont 在评论中指出的那样,如果不存在模板函数声明,表达式 get<0>(ar)
将被解析为 (get<0)>(ar)
,即作为一系列比较表达式而不是函数调用。
请注意,由于 P0846R0,这在 C++20 中发生了变化。一个非限定名称后跟一个 <
标记,普通的非限定查找找到一个或多个函数或什么也找不到,现在假定为命名模板,并且 <
被相应地解析。