首页 > 编程语言 >浅谈 c++ adl 机制

浅谈 c++ adl 机制

时间:2022-11-11 20:45:16浏览次数:36  
标签:std f1 浅谈 cow c++ solve ff adl

namespace f1{
	namespace f2{
		struct cow{
			friend void solve(cow){cout<<"f1::f2::cow";}
		};
	}
	void solve(f2::cow){cout<<"f1\n";}
	namespace f2{
		void solve(cow){cout<<"f1::f2\n";}
	}
}
void solve(f1::f2::cow){cout<<"::";}
namespace g1{
	void solve(f1::f2::cow){cout<<"g1";}
	namespace g2{
		void solve(f1::f2::cow){cout<<"g1::g2";}
		void print(){solve(f1::f2::cow{});}
	}
}

相信看到这段代码,很多人都会感到害怕,这个 print 究竟会输出什么呢?其实这段代码会 CE

先说说什么是 adl,很好理解,就是调用的函数会在参数的命名空间里查找。比如我有个 std::string b,我要统计里面有多少个空格,那就是 std::count(b.begin(),b.end(),' '),返回值就是空格的数量。
看这么一段代码:

namespace ff{
	struct cow{};
	cow operator+(const cow &x,const cow &y){
		return cow{};
	}
}
ff::cow solve(){
	ff::operator+(ff::cow{},ff::cow{});
	return ff::cow{}+ff::cow{};
}

假如没有 adlsolve 里面的加法必须以第一种方式显式调用这样才能调用到这个函数,但是有 adl 的情况下,ff::operator+ 可以直接由 ff::cowadl 到。让很多情况方便了不少。

接下来看看上面那段代码,首先排除的是 ::solveg1::solve,都被 g1::g2::solve 给遮盖了(局部屏蔽全局),f1::solve 由于 adl 只会往外找同一层命名空间,所以并不会被 adl 到。这个时候 g1::g2::solve(和函数本身就在同一命名空间) 和 f1::f2::solve(通过 adl 找到) 和 f1::f2::cow::solve(类内友元,也能通过 adl 找到)具有同等地位,所以就会导致 CE。

至于 adl 的实际价值就是节省码量,拓宽函数的寻找范围,很多本来要 std:: 的都可以省略。

endl(std::cout<<a[2]);
flush(std::cout<<"! 3\n");// cout 作参数
std::cout<<std::endl;// 注意这里的函数是 operator<<
operator<<(std::cout,std::endl);// 注意这里的函数是 operator<<
(std::endl)(std::cout<<"4\n");// 加上括号,没法 adl,必须写 std::endl
std::pair<int,int>a[3];
sort(a,a+3);// 指针也可以 adl

标签:std,f1,浅谈,cow,c++,solve,ff,adl
From: https://www.cnblogs.com/bxjz/p/adl.html

相关文章

  • C++代码实现计算组合数(3种计算方式)
    题目:输入两个非负整数n和m,返回组合数\(C^m_n\)。例如当n=10,m=2时,答案为45。组合与排列先从排列数开始说起,排列数是指从n个不同的元素中任意取出m(\(m\leqn\))个......
  • 浅谈 c++20 ranges 的用法
    ranges库是c++20开始具有的语法,对应的头文件是#include<ranges>。为了防止CE我一般都这么写:#if__cplusplus>=202002L#include<ranges>usingnamespacestd::view......
  • 浅谈Object类和包装类
    Object类简介Object类接收任意类型的对象toString方法equals方法包装类简介包装类的应用Object类简介Object类是java的一个内置类,属于java.lang包,此包下的所有类......
  • c++---纯虚类
    /*****************************************************************//***\file源.cpp*\brief**\authorDuan*\dateNovember2022***********......
  • 关于Redhat中-libstdc++软件包的说明
    本文OS版本:RedHatEnterpriseLinuxrelease8.6(Ootpa) 关于libstdc++软件包的说明如下:Summary:GNUStandardC++LibraryDescription:Thelibstdc++packagec......
  • C# 浅谈 接口(Interface)的作用
    继承"基类"跟继承"接口"都能实现某些相同的功能,但有些接口能够完成的功能是只用基类无法实现的1.接口用于描述一组类的公共方法/公共属性.它不实现任何的方法或属性,只是......
  • [C++]对照代码学习反汇编
    程序代码:1#include<iostream>23intmain()4{5inti,j,k;6intresult=0;7for(i=1;i<=4;i++)8for(j=1;j<=4;......
  • C++类中使用静态成员变量
    如果需要在类中使用静态成员变量,需要在头文件和.cpp文件各定义一次例如,有StaticTest.h和StaticTest.cpp两个文件StaticTest.h:classStaticTest{private:static......
  • 【Java】随机数原理 Random ThreadLocalRandom
    大致生成原理:随机数由seed经过一定的转换生成。需要提供初始seed。每一次生成随机数时,先由老seed生成新seed,再根据新seed生成新的随机数。由于算法是固定的,所以如果初始seed......
  • C/C++:探究二维数组的数组名
    C/C++:探究二维数组的数组名与数组指针先提一嘴:一维数组的数组名对于一个一维数组而言,其数组名是该数组的首地址,也就是一个数组首元素的指针,如下:#include<stdio.h>int......