C++ ADL

  • 即在一个名称作为调用运算符的左操作数时,并且这个名字是一个无限定名称时,在无限定查找到的名字集合中额外增加的一个规则使集合范围扩大(从而可以定位到其他一些限定名称),通常是用来保证定义在不同命名空间的运算符得以直接调用而非使用到全部名字(在限定符号存在的情况下,必须包含完整的名字例如+ => operator + )
  • 因此可以知道,ADL(argument dependent lookup)会发生在一个无限定函数名称调用时的名称查找过程中,但是若出现了,非ADL或函数本身是类成员(包括静态),块作用域内已经声明的(非using声明),非函数或函数模板时,则不会进行ADL.
  • 对于参数依赖查找有以下规定:
    • 若参数为:类类型,则查找范围是包含该类型的最内层名空间(或类)和类本身以及其直接或间接基类,并且如果存在inline时:
      • 若包含了改类(基类)的名称空间inline于另一个名称空间,则另一个名称空间内的名字也可以被找到(或是存在另一个名称控件inline与该名称空间内),但是如果只是单纯的名称控件或类嵌套,在无限定查找不到的情况下是查找不到包含该类或名称空间的最内层名称空间(类)的外围名称空间(类)的,例子:
      namespace N{
      inline namespace NS1{
      struct A{
      friend void FuncA(A){}              //在类内查找的只有友元,因为其他的均为类成员
      };
          void FN1(A){}
      }
          void FN(NS1::A){}
      }
      struct B:N::NS1::A{
          friend void FuncB(B){}
      };
      namespace E{
      namespace NS2{
      struct C:B{
          friend void FuncC(C){}
      };
          void FN2(C){}
          inline namespace NiS2{
              void FiS2(C){}
          }
      }
          void FE(NS2::C){}
      }
      void foo(){
          E::NS2::C s;
          FN2(s);
          FuncC(s);
          FuncB(s);
          FN1(s);
          FuncA(s);
          FN(s);
          FiS2(s);
          //FE(s);    查找不到
      }
      struct A{
          struct B{
              struct C{
      
              };
              friend void F(C){}
          };
          friend void F1(B::C){}
      };
      void foo(){
          A::B::C s;
          F(s);
          //F1(s);
      }
      namespace N{
          struct E{
              struct A{
                  struct B{
      
                  };
              };
              friend void F2(A::B){}
          };
          void F(E::A::B){}
      }
      void Foo(){
          N::E::A::B s;
          F(s);
          //F2(s);
      }
    • 若参数类型为模板的特化,该特化遵循上述规则外,对于每个模板类型实参,若为类类型的,遵循上述规则,若为模板模板形参则不会包含该模板模板形参在内,但是会包含该模板模板形参所被包含的(是其成员的)类或名称空间例:
    template<template<class D>class TY,class ... Ty>
    struct T{};
    namespace N2{
        struct B;    
    }
    namespace N3{
        struct N{
            template<class D>
            struct TY;
            friend void F1(T<TY,N2::B>){}
        };
    }
    namespace N1{
        struct A{
    
        };
        void F3(T<N3::N::TY,N2::B>){}
    }
    namespace N2{
        struct B:N1::A{
    
        };
    }
    namespace N3{
        template<class D>
        struct N::TY{
            friend void F4(T<TY,N2::B>){}
        };
    
        void F2(T<N::TY,N2::B>){}
    }
    void foo(){
        T<N3::N::TY,N2::B> s;
        F1(s);
        F2(s);
        F3(s);
        //F4(s);
    }
    • 对于指针类型则对指针指向的类型进行上述检查除非:
      • 该指针指向函数指针,则对该函数类型的返回值和参数进行上述检查
      • 该指针是类成员指针
        • 类成员函数指针,除了对函数参数和返回值进行上述检查之外还包括该类按照上述类规则检查
        • 类数据成员指针,对该类按照上述类规则检查
    • 补充点:
      • 在类中除了成员函数的查找外,若在类外调用,如static成员函数,规定,为了进一步的ADL处理,将会忽略所有在类中找到的声明,除了引入到了其最内层名称空间内的(此时就说明了友元的引入位置,但是在类内定义的友元函数是无法直接用限定访问查找到的)
      • 忽略查找集合(即上述所有规则中可以被查找到的位置)中的using 指令

转载于:https://www.cnblogs.com/A001/p/10632133.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值