The following code does not compile in C++17 but from C++20 on:
以下代码不能在C++17中编译,而是从C++20开始编译:
#include <tuple>
int main() {
auto t = std::make_tuple(1, 2);
get<0>(t); // no std:: required!
return 0;
}
Since this works with both g++ and clang++ and both -stdlib=libc++
and -stdlib=libstdc++
and even in msvc with /std:c++20
, I wonder whether this is a "feature". What is the rationale behind this? Is there more pollution to the global namespace besides this?
由于这既适用于g++和clang++,也适用于-stdlib=libc++和-stdlib=libstdc++,甚至在带有/std:c++20的msvc中也适用,所以我想知道这是不是一个“特性”。这背后的理由是什么?除此之外,是否还有更多对全局命名空间的污染?
更多回答
I disagree with the duplicate mark, as ADL is only half of the explanation... But since there is already an excellent answer, it doesn't really matter.
我不同意重复标记,因为ADL只是解释的一半…但既然已经有了一个很好的答案,这实际上并不重要。
优秀答案推荐
std::get
is found by argument-dependent lookup (ADL), because t
has a type that is a specialization of the class template std::tuple
which is located in the same namespace scope as the std::get
overload you want to use. This is behavior that has always existed in C++ and is fundamental to making operator overloading work, as well as other customizable function calls like swap
.
Std::Get是通过参数相关查找(ADL)找到的,因为t的类型是类模板std::tuple的专门化,它位于与要使用的std::Get重载相同的命名空间作用域中。这是C++中一直存在的行为,是使操作符重载以及其他可定制函数调用(如SWAP)工作的基础。
The reason it fails in C++17 has nothing to do with whether std::get
is found, but rather with the rules that determine whether or not the <
following get
is the less-than operator or the start of an template argument list. Before C++20, if the unqualified name before the <
wasn't found at all by usual unqualified (non-ADL) lookup, the program was ill-formed. Since C++20 it is assumed to introduce a template argument list in this situation.
它在C++17中失败的原因与是否找到std::GET无关,而是与确定<后面的GET是小于操作符还是模板参数列表的开始的规则有关。在C++20之前,如果通过通常的非限定(非ADL)查找根本找不到<前面的非限定名称,那么程序就是格式错误的。从C++20开始,假设在这种情况下引入模板参数列表。
For example, if you add a function template named get
, regardless of signature, e.g.
例如,如果添加一个名为GET的函数模板,而不考虑签名,例如
template<typename T>
void get();
into your global namespace scope, then <
will also be assumed to introduce a template argument list because this function template is found for get
by usual unqualified lookup, even in C++17. Then ADL applies to the call as usual (this has always worked this way in every C++ edition) and std::get
will be found as candidate as well.
在您的全局命名空间作用域中,则还将假定<引入一个模板参数列表,因为这个函数模板是通过通常的非限定查找为GET找到的,甚至在C++17中也是如此。然后,ADL照常应用于调用(这在每个C++版本中总是以这种方式工作),并且STD::GET也将被发现为候选者。
更多回答
我是一名优秀的程序员,十分优秀!