ADL and typedefs

ADL and typedefs

本文关键字:typedefs and ADL      更新时间:2023-10-16

简而言之,我试图理解C++中参数依赖查找的行为。ISO/IEC 14882:2017(E(中关于ADL的一些陈述我不清楚。我希望有人能向我澄清它们。

根据标准,

用于指定类型的 Typedef 名称和 using-声明对此集合没有贡献。

考虑关联的命名空间时,查找与在 关联的命名空间用作限定符 (6.4.3.2(,但以下情况除外:

  • 关联命名空间中的任何 using 指令都将被忽略...

对我来说,这些陈述意味着ADL应该完全忽略任何typedefusing发生。可能并非如此。请考虑以下示例:

#include <iostream>                                                             
using namespace std;                                                            
namespace N2                                                                 
{
struct B {};
template <typename T>                                                       
void func (const T&) {cout << __PRETTY_FUNCTION__ << endl;}  
};
namespace N                                                                     
{
typedef N2::B C;             
}                                                                               
void tfunc (N::C) {}                                                     
int main ()                                                     
{                                                                                                                      
func(tfunc);                                                                 
}

它工作,即编译器能够找到func。那么,标准中的那些引用实际上意味着什么?

这个答案是由@IgorTandetnik提供的。

该标准所说的是N2tfunc的相关命名空间中,但N不是。换句话说,无效tfunc (N::C)的工作方式与void tfunc(N2::B)完全相同。如果在示例中将 func 移动到N,则不会找到它,尽管表面上,tfunc的声明提到了N

实际上,如果你只是进一步阅读标准,你就会明白为什么你的代码有效。具体来说,N3337 [basic.lookup.argdep]/2 如下所示 [强调我的]:

命名空间和类集按以下方式确定:

如果 T 是函数类型,则其关联的命名空间和类是与函数关联的命名空间和类参数类型以及与返回类型关联的参数类型。

如您所见,如果传递的参数是函数类型(在您的情况下tfunc(,则与所有参数关联的类型(N2::B是唯一的类型(以及返回类型(void- 基本类型,因此不计算在内(被视为创建一组关联的命名空间。