根据名称找出所有适用的函数和函数模板对于适用的函数模板,要根据实际情况对模板形参进行替换; 替换过程中如果发生错误,这个模板会被丢弃 在上面两步生成的可行函数集合中,编译器会寻找一个最佳匹配,产生对该函数的调用...SFINAE表示替换失败不是错误( Substitution Failure Is Not An Error)。简单地说,替换就是尝试用提供的类型或值替换模板参数的机制。...再来回顾一下上述的简单理解:替换就是尝试用提供的类型或值替换模板参数的机制。在某些情况下,如果替换导致无效代码,编译器不应该抛出大量错误,而应该继续尝试其他可用的重载。...在decltype中,将评估所有表达式,但仅将最后一个表达式视为该类型。序列化不需要任何更改,减去了STL中现在提供了enable_if函数的事实。...container将负责保留lambda的未命名类型以供以后使用。
C++ 2.0 的局限性: 没有命名空间:C++ 2.0 并没有引入命名空间(namespace),因此容易出现命名冲突的问题。...命名空间: C++98 引入了 命名空间(namespace),用于避免名称冲突,尤其是在大型项目中。...示例代码:C++98 的常见特性 以下是一个综合示例,展示了 C++98 中的几个核心特性,包括模板、标准库(STL)、命名空间和异常处理。...使用 std::enable_if 和 std::is_integral 来判断 T 是否为整数类型,并分别调用不同的函数。SFINAE 机制可以避免无效的模板实例化,确保了代码的类型安全。...总结: C++03 是一个对 C++98 的修正版本,主要修复了一些语言规范中的小错误和不一致性,改进了模板、STL 和编译器的兼容性。
); // 调用第二个printNumber模板 printNumber("Hello"); // 错误,没有匹配的模板可用 return 0; } 在上面的示例中,我们定义了两个重载的函数模板...enable_if用于在编译时选择正确的模板。 对于整数类型,std::is_integral::value为true,因此第一个函数模板会被选择。...如果我们尝试传递一个非数字类型(如字符串),则会导致编译错误,因为没有匹配的模板可用。...enable_if还可以与其他模板元编程技术结合使用,例如std::enable_if_t、std::conditional等,以实现更复杂的条件选择和类型推导。...enable if 是一个模板元编程工具,使用 typename std::enable_if::type 的形式将其应用于模板参数或函数返回类型。
这种机制类似于: 文件系统的目录结构 互联网的域名系统 现实中的邮政编码体系 二、命名空间的核心语法(Core Syntax) 2.1 基础定义 namespace PhysicsEngine...} ADL三原则: 只考虑实参关联的命名空间 忽略using指令引入的名称 标准库ADL的特别处理 5.2 命名空间与模板特化 namespace MyLib { template...namespace DerivedNS { class Derived : public BaseNS::Base { // 必须完全限定 // ... }; } 7.3 模板元编程中的问题...s; // std::string类型 auto duration = 300ms; // std::chrono::milliseconds 通过本指南的系统学习,开发者应该能够:✅ 合理设计项目命名空间结构...✅ 有效避免名称冲突 ✅ 正确使用高级命名空间特性 ✅ 编写可维护的跨平台代码。
为了解决因为代码圈复杂度产生的代码质量问题,C++11提供了type_tratis类型萃取功能,在一定程度上可以消除冗长的代码分支语句,降低圈复杂度进而提升代码的可维护性。...D: true 1.4 获取可调用对象返回类型的traits std::result_of可以在编译器获取可调对象的返回类型,帮助解决编码过程中如下问题: 函数入参为模板参数,不能直接确定函数返回类型...main() { Fun(1); return 0; } 程序运行为最终会匹配到第二个模板函数,但是在实际的匹配过程中,当匹配到void Fun(T*)时用整数对T*进行替换是错误的,但是编译器会继续匹配...,直到匹配到void Fun(T)后执行正确的函数,这种规则就是SFINAE;反之,如果一个模板函数都没有匹配到,则编译器会报如下错误: error: no matching function for...因此,它可以在编译期间检查模板参数是否有效。使用std::enable_if可以实现一个强大的重载机制,充分利用可以减少或者消除圈的复杂度。如:根据不同的数据基本类型转换为string进行输出。
第二版书籍覆盖了 c++ 11 14 和 17 标准,值得程序猿们精读学习,特此整理学习笔记,将每一部分自认为较为重要的部分逐条陈列,并对少数错误代码进行修改 一、函数模板 1.1 函数模板初探 1.模板实例化时...#include #include // 错误定义 deque 中的模板参数有两个:类型和默认参数allocator // 而模板模板参数Cont的参数只有类型Elem...b.若表达式结果为 false,根据替换失败并非错误的原则,包含 std::enable_if 的模板将会被忽略。...模板在编译期会进行实例化,实例化时需要提供模板的定义,所以对于模板相关代码,正确用法是将声明和定义均置于头文件中。...函数模板可以有 c++链接,但不能有 C 链接。 函数模板一般具有外部链接,除非是 static 或定义在未命名的命名空间中。
在上面示例2中,通过汇编代码发现其是在运行期求值,那么有没有办法在编译期求值呢?...自C++17起,引入了if constexpr语句,在本节中,将借助SFINAE 和 std::enable_if来实现一个简单的Square功能,最后借助if constexpr对代码进行优化(如果对...,如果是算术类型,则调用第一个,否则调用第二个,完整代码如下: #include template typename std::enable_if代码中,为了编译成功,我们引入了两个Square()模板函数借助std::enable_if来实现,代码上多少有点冗余,在这个时候,本节的主角if constexpr 出场,完整代码如下: #include...我们借助一个Square()函数模板以及更加符合编码习惯的if语句就能解决上面的问题,且比使用std::enable_if方式更为优雅和符合阅读习惯,进而提高代码的可阅读性。
我们注意到两段错误都提到了operator-,实际上编译器认为错误在于std::sort中会把两个输入迭代器所属类型的实例相减,而std::list::iterator没有重载operator-运算符...requires关键词与需求 对模板参数的需求是嵌套的,深入到最底层,都是通过requires关键词实现的。“s”的存在使代码在英语的语法中更加通顺一点。...有些资料中的标准库concept是帕斯卡命名(PascalCase)的,因为最初的concept提案中是这样写的,原因可能是为了让它看起来属于新的C++20,或是与模板参数列表中类型大写的习惯一致。...);唯独第三条没有解决,导致冗长的模板错误,并且衍生出以SFINAE为代表的一些奇技淫巧。...的模板类型发生错误,根据SFINAE,该重载被忽略;与此同时第二个是可用的。
,绝大多数编译器都支持,得到了国际标准化组织(ISO)和美国标准化协会认可,以模板方式重写C++标准库,引入了STL(标准模板库) C++ 03 C++标准第二个版本,语言特性无大改变,主要:修订错误、...一般在大型项目中,如果没有命名空间,那么不同程序员负责的不同模块之间就极有可能会定义出相同名字的变量或函数名。...std命名空间的使用惯例:std是C++标准库的命名空间,如何展开std使用更合理呢? 在日常练习中,建议直接using namespace std即可,这样就很方便。...using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。...所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。
模板参数中增加了一个常量参数ZERO,用于编译期判断。...用到了名为std::enable_if的type_traits,它类似一个if语句,判断ZERO,当ZERO为true时编译器选择第一个版本的函数,反之选择第二个。...enable_if是C++11头文件中的一个类,关于enable_if的用法详细说明参见: class template std::enable_if...,但是却与C++14版本的make_unique在模板参数类型上并不兼容,你为啥知道C++14的make_unique版本是什么样呢?...的实现代码,代码中创建普通对象和数组对象的函数名都是make_unique,与我写的版本不一样,而且微软的版本中也没有区分是否在初始化数组,一律初始化为0。
我们知道,在opencl内核代码中,向量类型(vector data type)的数据可以像普通标量类型(scala data type)一样,用各种算术和逻辑运算符进行操作。...,但c/c++以及opencl的API本身并没有提供对这些向量类型的一般运算支持。...如果能像模板内核代码一样,为向量运算符提供简单的向量运算功能,就可以大大简化这些代码。 利用C++的模板计算函数,可以实现上面的功能。...(实现其他的运算符和函数也是差不多的代码,因为我暂时不需要就没有继续写下去)。...代码开始有两个很长的模板函数cl_vector_type和is_cl_vector,所有的其他函数模板都要用到这两个模板函数: cl_vector_type用于构造一个指定元素类型和长度的opencl
如果对传入的对象p加上const修饰,那么虽然模板函数虽然会被实例化成为一个接收const类型Person对象的函数,但是具有在const类型参数的所有重载函数中,C++中的重载解析规则是:当模板实例函数和非模板函数同样都能匹配一个函数调用...没有显式支持移动操作或不满足编译器自动生成移动操作的类型 并非所有支持移动的标准库容器都会受益于移动操作 对于把内容存储在堆内存中,而自身只保存指向该堆内存指针的容器类型来说,移动操作仅仅是拷贝这个指针到新的容器中...std::array没有这个特性,因为它把内容存储在自身空间中,即便存储的内容对象本身支持移动操作,且移动操作比拷贝要快,而且std::array也支持移动操作,但对于std::array来说,移动操作和拷贝操作代价一样...而标准规定:向函数模板传递一个花括号初始化的参数,而模板参数又没有指定参数类型为std::initializer_list,那么这就是一个不可推导的情况。...,也就没有内存空间。
,比如:正则表达式、基于范围for循环、auto关键字、新容器、列表初始化、标准线程库等 C++14 对C++11的扩展,主要是修复C++11中漏洞以及改进,比如:泛型的lambda表达式,auto的返回值类型推导...:比如Lambda支持模板、范围for支持初始化等 C++23 明确的对象参数(Deducing this)、if consteval、多维下标运算符、内建衰减复制支持、标记不可达代码(std::unreachable...相信掌握C语言语法的读者就会说,上面的代码是可以正常编译通过的。没错,上面的代码的确是没有任何问题的。 那如果我将上述的代码做了一点改变,代码还能正常编译过去吗?...using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。...所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。
, POD 库编程: 内联命名空间, 继承构造, 右值引用 C++11标准的设计准则: 在稳定性和兼容性之间抉择: auto, using, nullptr 用库而非扩展语言语法来实现特性: std::...原因和extern变量一样, 普通的模板只存在于对应文件的.o中, 如果一个模板文件被多个文件实例化就会产生多份重复代码, 没有extern的话此时重复的模板会冲突...., 这个union被称为变长成员 内联名字空间 namespace嵌套namespace后, 调用内部内容可能很繁琐 如果用using打开一些内层的空间又可能与模板编程冲突, 因为模板不允许不同名称空间的名字在模板中特化...如果在代码中看到了大量的std::enable_if, 那么要想到这是和SFINEA相关的模板编程特性...., 所以不会降低效率 标准库中的std::result_of()内部的type命名本质就是decltype decltype有所谓的推导四原则: 如果目标是一个没有带括号的标记符表达式(也就是除去关键字
这种名称可以指向: 类成员(包括静态和非静态函数、类型、模板等) 命名空间成员(包括另一个命名空间) 通常在命名空间的作用域查找。...查找仅考虑命名空间、类类型、枚举和模板特化(它们是类型)。如果左侧找到的名称不是指一个命名空间或类、枚举或依赖类型,程序是不正确的(ill-formed)。...然后对每个参数进行类型检查:对于函数调用表达式中的每个参数,会检查其类型以确定将添加到查找中的相关命名空间和类(具体不同类型对应的命名空间规则比较复杂,详见cppreference)接着关联集合:基于参数类型...如果没有找到声明,就会遇到一个语法错误,因为编译器会期望一个已知的名称后面跟一个小于号('代码解读复制代码namespace N1{ struct S {}; template...支持泛型编程:在模板编程中,ADL使得模板能够使用与模板参数类型相关的特定操作,而无需程序员显式地指定这些操作的命名空间。这使得模板更加通用和灵活。
错误#1:不将你的API放在命名空间中 为什么这是一个错误? 因为你不知道将使用哪个代码库,特别是对于外部API。...误#2:在你的公共API头的全局范围中包含“using namespace” 为什么这是一个错误? 这将导致被引用命名空间中的所有符号在全局命名空间中变得可见,并首先抵消掉使用命名空间的好处。...错误#9:使用隐式模板实例化时,使用模板实现细节来混淆公共头文件 在隐式实例化中,模板代码的内部必须放在头文件中。没有其他办法。...它缩短了客户端的构建时间,使你不必密封模板中未经测试的类型,并将模板代码逻辑隐藏在cpp文件中。...#define不为你定义的常量提供任何类型检查,并且可能导致我们对隐式转换和舍入错误感到疑惑。 #define语句是全局的,不限于特定的范围,例如在单个类中。因此它们可以污染客户的全局命名空间。
SFINE性质,也就是只要可以匹配成功,即使某些场景匹配失败也不是错误。...typedef T type; }; using 在模版中的使用 using 有给类型重命名的作用,也有继承父类所有构造函数的作用,比如: struct Base { int val;...还有一层含义,就是修饰的参数一定是类型。...void foo() { typename T::SubType* ptr; } }; 这儿的 T::SubType 是类型。... 就可以表示 is_const::value 模版模版参数 如果模版参数中的类型本身也是一个模版,比如还是Stack, Stackstd::vector> 可以看到第一个模版参数是
上述代码中,我们通过__register_type()创建的ClassBuilder提供的。...(二)使用的代码 运行时我们获取到的也是类型擦除后的Function对象,如上例中的 dotProductFunc,所以运行时我们需要通过runtime命名空间下提供的辅助设施runtime::call...需要注意的是并没有Invoke的方法,这个主要是因为不同用途(如纯C++的调用,和for lua的Invoke,类型擦除后的调用方式会略有差异)。...,变为统一的类型(上一节中Function对象)存入MetaClass中组织起来,方便运行时动态使用的过程。...,注意此处对于Covert错误的处理是直接抛异常。
绝大多数编译器都支持,得到了国际标准化组织(ISO)和美国标准化协会认可,以模板方式重写C++标准库,引入了STL(标准模板库) C++03 C++标准第二个版本,语言特性无大改变,主要:修订错误、减少多异性...,比如:正则表达式、基于范围for循环、auto关键字、新容器、列表初始化、标准线程库等 C++14 对C++11的扩展,主要是修复C++11中漏洞以及改进,比如:泛型的lambda表达式,auto的返回值类型推导...命名空间的定义 定义命名空间 需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。...; } std命名空间的使用惯例: std是C++标准库的命名空间,如何展开std使用更合理呢?...在日常练习中,建议直接using namespace std即可,这样就很方便。 在项目开发中,由于代码多,规模大,不建议直接展开使用 写项目使用时,应该使用指定命名空间展开常用对象的方式 3.
领取专属 10元无门槛券
手把手带您无忧上云