模板

您所在的位置:网站首页 t2模板 模板

模板

2024-06-20 21:00| 来源: 网络整理| 查看: 265

  C++ 语言 标准库头文件 自立与有宿主实现 具名要求 语言支持库 概念库 (C++20) 诊断库 工具库 字符串库 容器库 迭代器库 范围库 (C++20) 算法库 数值库 本地化库 输入/输出库 文件系统库 (C++17) 正则表达式库 (C++11) 原子操作库 (C++11) 线程支持库 (C++11) 技术规范  C++ 语言 模板 形参与实参 类模板 函数模板 类成员模板 变量模板(C++14) 模板实参推导 类模板实参推导(C++17) 显式(全)特化 部分特化 待决名 形参包(C++11) sizeof...(C++11) 折叠表达式(C++17) SFINAE 制约与概念(C++20)  

模板是定义下列之一的 C++ 实体:

一族类(类模板),可以是嵌套类 一族函数(函数模板),可以是成员函数 一族类型的别名(别名模板) (C++11 起) 一族变量(变量模板) (C++14 起) 概念(制约与概念) (C++20 起)

模板以一或多个模板形参参数化,形参有三种:类型模板形参、非类型模板形参和模板模板形参。

当提供了模板实参,或仅对于函数和类 (C++17 起)模板,当模板实参被推导出时,它们替换各模板形参,以获得模板的一个特化(specialization),即一个特定类型或一个特定函数左值。特化亦可显式提供:对类、变量 (C++14 起)和函数模板都允许全特化,只允许对类模板与变量模板 (C++14 起)部分特化。

在要求完整对象类型的语境中引用某个类模板特化时,或在要求函数定义存在的语境中引用某个函数模板特化时,除非模板已经被显式特化或显式实例化,否则模板即被实例化(instantiate)(它的代码被实际编译)。类模板的实例化不会实例化其任何成员函数,除非它们也被使用。在连接时,不同翻译单元生成的相同实例被合并。

模板的定义必须在隐式实例化点可见,这就是为何模板库通常都在头文件中提供所有模板定义的原因(例如大多数 boost 库仅有头文件)

语法 template 声明 (1) template requires-子句 声明 (2) (C++20 起) export template 声明 (2) (C++11 前) template concept 概念名 = 制约表达式 ; (3) (C++20 起) 声明 - 类(包括 struct 和 union),成员类或成员枚举类型,函数或成员函数,命名空间作用域的静态数据成员,变量或类作用域的静态数据成员, (C++14 起)或别名模板 (C++11 起)的声明。它亦可定义模板特化。 形参列表 - 非空的模板形参的逗号分隔列表,其中每项是非类型形参、类型形参、模板形参或任何这些的形参包之一。 概念名制约表达式 - 见制约与概念 (C++20 起)

export 是一个可选的修饰符,声明模板被导出(用于类模板时,它声明其所有成员也被导出)。对被导出模板进行实例化的文件不需要包含其定义:有声明就足够了。export 的实现稀少而且在细节上互不一致。

(C++11 前)

模板形参列表可以后随一个可选的 requires-子句,它指定各模板实参上的制约。

(C++20 起) 本节未完成原因:核心语法,模板形参,以及实例化,带出 class_template 和 function_template 间的公共内容 模板标识 模板名 模板名 - 或为指名模板的标识符(该情况下称之为 "简单模板标识" ),或为重载运算符模板或用户定义字面量模板的名字。

指名模板特化的 简单模板标识 指名一个类。

指名别名模版特化的 模板标识 指名一个类型。

指名函数模板特化的 模板标识 指名一个函数。

模板标识 仅当符合下列条件才合法

实参数量不多于形参,或有形参是模板形参包, 每个无默认模板实参的不可推导的非包形参都有一个实参, 每个模板实参都与对应的模板形参相匹配, 替换每个模板实参到其后续模板形参(若存在)中均成功,而且 若 模板标识 非待决,则其关联制约得以满足,如下所述。 (C++20 起)

无效的 简单模板标识 是编译时错误,除非它指名的是函数模板特化(该情况下可适用 SFINAE)。

template class X; struct S { using type = int; }; using T1 = X; // 错误:过多实参 using T2 = X; // 错误:第一模板形参无默认实参 using T3 = X; // 错误:值 1 不匹配类型实参 using T4 = X; // 错误:第二模板形参替换失败 using T5 = X; // OK

如果在 简单模板标识 的模板名指名受制约的非函数模板或受制约的模板模板形参,但不是作为未知特化的成员的成员模板,而且 简单模板标识 中的所有模板实参均非待决,则必须满足受制约模板的各项关联制约:

template concept C1 = sizeof(T) != sizeof(int);   template struct S1 { }; template using Ptr = T*;   S1* p; // 错误:不满足制约 Ptr p; // 错误:不满足制约   template struct S2 { Ptr x; }; // 错误,不要求诊断   template struct S3 { Ptr x; }; // OK:不要求满足   S3 x; // 错误:不满足制约   template struct S4 { X x; // 错误,不要求诊断 };   template concept C2 = sizeof(T) == 1;   template struct S { };   template struct S; // 错误:不满足制约 template struct S { }; // 错误:不满足制约 (C++20 起)

若二个 模板标识

其 模板名 指代同一模板,且 其对应类型模板实参为同一类型,且 其对应非类型模板实参在转换到模板形参的类型后模板实参等价,且 其对应的模板模板实参指代同一模板。

相同的二个 模板标识 指代同一变量、 (C++14 起)类或函数。

模板化实体

模板化实体(某些资料称之为 "temploid")是任何定义(或对于 lambda-表达式 为创建)于模板定义内的实体。下列所有实体都是模板化实体:

类/函数/变量 (C++14 起)模板 概念 (C++20 起) 模板化实体的成员(例如类模板的非模板成员函数) 作为模板化实体的枚举的枚举项 任何模板化实体中定义或创建的实体:局部类,局部变量,友元函数,等等 模板化实体的声明中出现的 lambda 表达式的闭包类型

例如,以下模板中

template struct A { void f() {} };

函数 A::f 不是函数模板,但仍被当做是模板化的。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3