以下代码按预期失败,因为未发现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个编译器中的错误(可能不是),还是我缺少某些东西?
此行为已在
中进行了测试编辑: 我知道ADL。但是,如果ADL使第二个代码起作用,那么为什么在第一部分中却没有呢?
答案 0 :(得分:20)
ADL。您正在使用非限定形式的get
和非类型模板参数0
,因此您需要引入模板函数声明或将get
的限定版本用作{{1 }}。
以标准语std::get<0>(ar)
:(强调我的意思)
[注意:对于简单的函数名称,即使在调用范围内看不到函数名称,也要使用基于参数的查找(6.4.2)。这是因为该调用仍具有函数调用(6.4.1)的语法形式。 但是,当使用带有显式模板参数的函数模板时,调用将没有正确的语法形式,除非在调用时有一个名称可见的函数模板。如果看不到这样的名称,则该调用的语法格式不正确,并且依赖于参数的查找也不适用。如果某些此类名称可见,则将应用依赖于参数的查找,并且可能在其他名称空间中找到其他功能模板。
编辑:
正如@Yakk-Adam Nevraumont在评论中指出的,如果不存在模板函数声明,则表达式[temp.arg.explicit]/8
将被解析为get<0>(ar)
,即作为比较表达式的一部分函数调用。
答案 1 :(得分:4)
请注意,由于P0846R0,这在C ++ 20中已更改。现在假定使用不合格名称后跟x <- c(0.1, 0.2, 0.3, 0.2, 0.1, 0.1)
df <- as.data.frame(x)
df %>% mutate(cumsum = cumsum(x))
令牌,而普通不合格查找针对该令牌找到一个或多个函数或什么都不找到,则命名模板,并据此对<
进行解析。