当前位置: 首页 > article >正文

第十四章:模板实例化_《C++ Templates》notes

模板实例化

      • 核心知识点解析
      • 多选题
      • 设计题
      • 关键点总结

核心知识点解析

两阶段查找(Two-Phase Lookup)
原理
模板在编译时分两个阶段处理:

  1. 第一阶段(定义时):检查模板语法和非依赖名称(Non-dependent Names),此时不依赖模板参数。
  2. 第二阶段(实例化时):检查依赖名称(Dependent Names),并绑定到具体类型。

代码示例

#include <iostream>template<typename T>
void foo(T t) {// 非依赖名称:在编译时检查bar(t);  // 第一阶段查找bar(),若未声明则报错// 依赖名称:在第二阶段实例化时查找t.func(); 
}void bar(int) { std::cout << "bar(int)\n"; }struct Data {void func() const { std::cout << "Data::func()\n"; }
};int main() {foo(42);     // 实例化foo<int>,调用bar(int)和Data::func()return 0;
}

测试用例

// 输出:
// bar(int)
// Data::func()

  1. 实例化点(Point of Instantiation, POI)
    原理
    模板实例化的位置由POI决定,通常位于首次使用模板的最近命名空间作用域之后。

代码示例

template<typename T>
void baz() { /* ... */ }void test() {baz<int>();  // 触发baz<int>的实例化
}// POI位于test()之后,此处可访问baz<int>

测试用例

// 正确:POI在test()之后

  1. 显式实例化(Explicit Instantiation)
    用途
    手动控制模板的实例化位置,避免重复实例化。

代码示例

template<typename T>
T add(T a, T b) { return a + b; }// 显式实例化int版本
template int add<int>(int, int);int main() {add(1, 2);   // 使用显式实例化的版本return 0;
}

测试用例

// 输出:3

  1. 编译期if constexpr(C++17)
    原理
    在编译期根据条件选择代码分支,未使用的代码会被丢弃。

代码示例

template<typename T>
auto get_value(const T& t) {if constexpr (std::is_pointer_v<T>) {return *t;} else {return t;}
}int main() {int x = 5;int* p = &x;std::cout << get_value(x) << "\n";   // 输出5std::cout << get_value(p) << "\n";   // 输出5return 0;
}

测试用例

// 输出:
// 5
// 5

综合测试程序
以下将所有知识点整合到一个测试程序中:

#include <iostream>
#include <type_traits>// 两阶段查找示例
template<typename T>
void foo(T t) {bar(t);          // 非依赖名称,第一阶段需可见t.func();        // 依赖名称,第二阶段实例化时查找
}void bar(int) { std::cout << "bar(int)\n"; }struct Data {void func() const { std::cout << "Data::func()\n"; }
};// 显式实例化示例
template<typename T>
T add(T a, T b) { return a + b; }template int add<int>(int, int);  // 显式实例化int版本// 编译期if constexpr示例
template<typename T>
auto get_value(const T& t) {if constexpr (std::is_pointer_v<T>) {return *t;} else {return t;}
}int main() {// 测试两阶段查找foo(42);     // 调用bar(int)和Data::func()// 测试显式实例化std::cout << add(3, 5) << "\n";  // 输出8// 测试编译期if constexprint x = 10;int* p = &x;std::cout << get_value(x) << "\n";   // 输出10std::cout << get_value(p) << "\n";   // 输出10return 0;
}

输出结果

bar(int)
Data::func()
8
10
10

多选题

题目1:模板实例化的基本流程是?
A. 解析模板定义时立即生成代码
B. 使用时按需生成代码(按需实例化)
C. 显式实例化指令触发代码生成
D. 所有模板参数必须显式指定

答案:B, C
详解

  • B 正确:C++ 默认采用按需实例化,仅在用到模板时生成代码。
  • C 正确:通过 template class MyClass<int>; 可显式触发实例化。
  • A 错误:模板定义时不会立即生成代码。
  • D 错误:模板参数可通过推导自动确定。

题目2:两阶段查找(Two-Phase Lookup)的规则是?
A. 非依赖名称在模板定义时解析
B. 依赖名称在模板实例化时解析
C. 所有名称都在实例化时解析
D. ADL 仅在实例化阶段生效

答案:A, B
详解

  • A 正确:非依赖名称(如普通函数名)在模板定义时解析。
  • B 正确:依赖名称(如 T::func)在实例化时结合实参类型解析。
  • C 错误:非依赖名称提前解析。
  • D 错误:ADL 在两阶段均可能生效。

题目3:显式实例化声明(extern template)的作用是?
A. 防止模板在当前翻译单元实例化
B. 强制模板在其他地方实例化
C. 减少编译时间
D. 提升链接效率

答案:A, C
详解

  • A 正确:阻止隐式实例化,避免重复代码生成。
  • C 正确:通过集中实例化减少编译负担。
  • B 错误:仅声明不实现,无法强制实例化位置。
  • D 错误:链接效率取决于实现,非主要目的。

题目4:编译期if constexpr(C++17)与运行期if的关键区别是?
A. 编译期分支可能被完全剔除
B. 运行期if可处理非constexpr条件
C. 编译期if必须满足常量表达式
D. 两者均可用于模板元编程

答案:A, B, C
详解

  • A 正确:未选择的分支代码会被丢弃。
  • B 正确:运行期if无此限制。
  • C 正确:constexpr if条件需在编译期可求值。
  • D 错误:运行期if无法参与模板特化。

题目5:显式实例化与显式特化的区别是?
A. 显式实例化生成通用代码
B. 显式特化为特定模式提供定制实现
C. 显式实例化优先级高于显式特化
D. 显式特化需在命名空间作用域声明

答案:A, B
详解

  • A 正确:template class MyClass<int>; 生成MyClass<int>的代码。
  • B 正确:template<> void MyClass<int>::func() {...} 定制int版本的实现。
  • C 错误:显式特化优先于显式实例化。
  • D 错误:显式特化需在全局或类作用域声明。

题目6:以下哪种情况会导致模板实例化失败?
A. 成员函数模板推导失败
B. 构造函数默认参数未定义
C. 虚函数表生成时依赖未实例化的类型
D. 静态成员变量未显式初始化

答案:A, B, C
详解

  • A 正确:成员函数模板推导失败会导致实例化中止。
  • B 正确:构造函数默认参数若依赖未实例化的类型会失败。
  • C 正确:虚表生成需要完整类型信息。
  • D 错误:静态成员可在类外延迟初始化。

题目7:类模板成员的显式实例化方式是?
A. template void MyClass<int>::func();
B. template MyClass<int>::func();
C. extern template void MyClass<int>::func();
D. template<> void MyClass<int>::func();

答案:A
详解

  • A 正确:显式实例化成员函数的语法。
  • B 错误:缺少template关键字。
  • C 错误:extern用于声明而非定义。
  • D 错误:这是显式特化的语法。

题目8:编译期if constexpr的典型应用场景是?
A. 实现类型萃取(Type Traits)
B. 条件编译不同代码路径
C. 优化递归模板展开
D. 替代宏定义

答案:A, B, C
详解

  • A 正确:通过条件判断筛选类型特性。
  • B 正确:根据常量条件选择执行路径。
  • C 正确:避免无效分支的代码膨胀。
  • D 错误:constexpr if无法完全替代宏的语义。

题目9:模板实例化的存储优化技术包括?
A. 链接器去重(Linker Deduplication)
B. 内联展开(Inlining)
C. 空基类优化(EBO)
D. 全局变量合并

答案:A, B
详解

  • A 正确:链接器消除重复实例化的代码。
  • B 正确:小函数可能被内联以避免实例化。
  • C 错误:EBO与模板实例化无关。
  • D 错误:全局变量合并不适用于模板。

题目10:以下代码的输出是?

template<typename T> void foo(T) { cout << "T" << endl; }
template<> void foo<int>(int) { cout << "int" << endl; }
extern template void foo<double>(double);int main() {foo(1);    // Afoo(1.0);  // Bfoo('c');  // C
}

A. int
B. T
C. T

答案:A. int, B. T, C. T
详解

  • A 调用显式特化版本。
  • B 未显式实例化double,按需实例化通用版本。
  • C 字符字面量推导为char,调用通用版本。

设计题

题目1:实现一个线程安全的单例模式,要求支持任意类型T,并利用显式实例化优化性能。

#include <iostream>
#include <mutex>template<typename T>
class Singleton {
private:static T* instance;static std::once_flag flag;Singleton() = default;~Singleton() = default;public:Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;static T& getInstance() {std::call_once(flag, []{instance = new T();});return *instance;}
};// 显式实例化常用类型以优化性能
template<> Singleton<int>::instance = nullptr;
template<> std::once_flag Singleton<int>::flag;int main() {Singleton<int>& si = Singleton<int>::getInstance();Singleton<std::string>& ss = Singleton<std::string>::getInstance();return 0;
}

题目2:编写一个模板元函数is_pointer_v,检测类型是否为指针,并利用编译期if constexpr优化性能。

#include <iostream>
#include <type_traits>template<typename T>
constexpr bool is_pointer_v = false;template<typename T>
constexpr bool is_pointer_v<T*> = true;template<typename T>
void checkPointer(T val) {if constexpr (is_pointer_v<T>) {std::cout << "Pointer type" << std::endl;} else {std::cout << "Non-pointer type" << std::endl;}
}int main() {int a;int* p = &a;checkPointer(a);  // 输出 Non-pointer typecheckPointer(p);  // 输出 Pointer typereturn 0;
}

题目3:实现一个泛型缓存类Cache,支持通过键值快速访问对象,利用显式实例化减少模板代码膨胀。

#include <unordered_map>
#include <string>template<typename Key, typename Value>
class Cache {
private:std::unordered_map<Key, Value> storage;public:void set(const Key& key, const Value& value) {storage[key] = value;}Value get(const Key& key) {return storage[key];}
};// 显式实例化常用组合
template class Cache<std::string, int>;
template class Cache<int, std::string>;int main() {Cache<std::string, int> intCache;intCache.set("age", 25);std::cout << intCache.get("age") << std::endl;  // 输出 25Cache<int, std::string> strCache;strCache.set(1, "one");std::cout << strCache.get(1) << std::endl;  // 输出 onereturn 0;
}

题目4:设计一个支持多种序列化协议的模板类Serializer,利用显式实例化适配不同协议。

#include <iostream>
#include <string>enum class Protocol { JSON, XML };template<Protocol P>
class Serializer {
public:static std::string serialize(int value) {if constexpr (P == Protocol::JSON) {return "{\"value\":" + std::to_string(value) + "}";} else {return "<value>" + std::to_string(value) + "</value>";}}
};// 显式实例化常用协议
template class Serializer<Protocol::JSON>;
template class Serializer<Protocol::XML>;int main() {std::cout << Serializer<Protocol::JSON>::serialize(42) << std::endl;  // 输出 {"value":42}std::cout << Serializer<Protocol::XML>::serialize(42) << std::endl;   // 输出 <value>42</value>return 0;
}

题目5:实现一个类型萃取工具TypeTraits,利用编译期if constexpr简化类型判断逻辑。

#include <iostream>
#include <type_traits>template<typename T>
struct TypeTraits {static constexpr bool is_pointer = false;static constexpr bool is_reference = false;
};template<typename T>
struct TypeTraits<T*> {static constexpr bool is_pointer = true;
};template<typename T>
struct TypeTraits<T&> {static constexpr bool is_reference = true;
};template<typename T>
void analyzeType(const T& value) {if constexpr (TypeTraits<T>::is_pointer) {std::cout << "Pointer type" << std::endl;} else if constexpr (TypeTraits<T>::is_reference) {std::cout << "Reference type" << std::endl;} else {std::cout << "Value type" << std::endl;}
}int main() {int a = 5;int* p = &a;int& r = a;analyzeType(a);  // 输出 Value typeanalyzeType(p);  // 输出 Pointer typeanalyzeType(r);  // 输出 Reference typereturn 0;
}

代码测试说明

  1. 编译命令:使用支持C++17的编译器(如GCC 7+、Clang 5+):
    g++ -std=c++17 -o test test.cpp && ./test
    
  2. 测试要点
    • 每个设计题的main函数均包含测试用例。
    • 多选题答案需结合书中第十四章的实例化机制、两阶段查找规则等知识点验证。

关键点总结

  1. 两阶段查找:确保模板定义时非依赖名称可见,依赖名称在实例化时解析。
  2. 显式实例化:通过template关键字手动实例化,减少编译开销。
  3. if constexpr:编译期分支选择,优化生成的代码。

通过以上示例和测试,可以深入理解C++模板实例化的机制和优化技巧。

相关文章:

第十四章:模板实例化_《C++ Templates》notes

模板实例化 核心知识点解析多选题设计题关键点总结 核心知识点解析 两阶段查找&#xff08;Two-Phase Lookup&#xff09; 原理&#xff1a; 模板在编译时分两个阶段处理&#xff1a; 第一阶段&#xff08;定义时&#xff09;&#xff1a;检查模板语法和非依赖名称&#xff0…...

循环查询指定服务器开放端口(Python)

循环查询指定服务器开放端口列表 # Time : 2025/3/22 # Author : cookie # Desc :import socket import concurrent.futures from datetime import datetime# 设置目标IP和端口范围 target_ip input("请输入目标IP地址: ") start_port int(input("请输入…...

算法 | 蜣螂优化算法原理,引言,公式,算法改进综述,应用场景及matlab完整代码

蜣螂优化算法(Dung Beetle Optimizer, DBO)详解 1. 算法原理 蜣螂优化算法(DBO)是一种基于自然界蜣螂行为的元启发式优化算法,灵感来源于蜣螂的滚球、繁殖、觅食和偷窃行为。其核心思想是通过模拟蜣螂在复杂环境中的协作与竞争机制,解决全局优化问题。关键行为模拟: 滚球…...

排序复习_代码纯享

头文件 #pragma once #include<iostream> #include<vector> #include<utility> using std::vector; using std::cout; using std::cin; using std::endl; using std::swap;//插入排序 //1、直接插入排序&#xff08;稳定&#xff09; void InsertSort(vecto…...

【STM32】第一个工程的创建

目录 1、获取 KEIL5 安装包2、开始安装 KEIL52.1、 激活2.2、安装DFP库 3、工程创建4、搭建框架5、开始编写代码 1、获取 KEIL5 安装包 要想获得 KEIL5 的安装包&#xff0c;在百度里面搜索“KEIL5 下载”即可找到很多网友提供的下载文件&#xff0c;或者到 KEIL 的官网下载&a…...

SpringBoot+策略模式+枚举类,优雅消除if-else

需求分析 公司做物联网系统的&#xff0c;使用nettry进行设备连接&#xff0c;对设备进行数据采集&#xff0c;根据设备的协议对数据进行解析&#xff0c;解析完成之后存放数据库&#xff0c;但是不同厂家的设备协议不同。公司系统使用了使用了函数式编程的去写了一个解析类&am…...

前端框架学习路径与注意事项

学习前端框架是一个系统化的过程&#xff0c;需要结合理论、实践和工具链的综合掌握。以下是学习路径的关键方面和注意事项&#xff1a; 一、学习路径的核心方面 1. 基础概念与核心思想 组件化开发&#xff1a;理解组件的作用&#xff08;复用性、隔离性&#xff09;、组件通信…...

kubeval结合kube-score实现k8s yaml文件校验

一、工具定位与互补性 工具核心能力检查范围kubeval校验 YAML 语法和 API 版本兼容性确保资源配置符合 Kubernetes 版本规范kube-score检查安全配置与最佳实践识别资源限制缺失、权限过高等问题 协同作用&#xff1a; kubeval 确保配置文件的语法正确性&#xff0c;避免低级错…...

Linux驱动开发-①platform平台②MISC字符驱动框架③input框架

Linux驱动开发-①platform平台②MISC字符驱动框架③input框架 一&#xff0c;platform1.1 platform框架&#xff08;设备树下&#xff09;1.2 platform框架&#xff08;配置设备函数&#xff09; 二&#xff0c;MISC字符驱动框架三&#xff0c;input框架 一&#xff0c;platfor…...

【mysql】唯一性约束unique

文章目录 唯一性约束 1. 作用2. 关键字3. 特点4. 添加唯一约束5. 关于复合唯一约束 唯一性约束 1. 作用 用来限制某个字段/某列的值不能重复。 2. 关键字 UNIQUE3. 特点 同一个表可以有多个唯一约束。唯一约束可以是某一个列的值唯一&#xff0c;也可以多个列组合的值唯…...

pytest的测试报告allure

1、安装jdk,安装allure、下载allure,配置环境变量 1.1、下载地址:https://repo.maven.apache.org/maven2/io/qameta/allure/allurecommandline 找到最新版本下载即可 【下载zip包】解压到任意目录,建议目录不要在C盘 不要太深 最好不要有中文;进入allure解压后的目录,找到…...

常见中间件漏洞:Jboss篇

CVE-2015-7501 环境搭建 cd vulhub-master/jboss/JMXInvokerServlet-deserialization docker-compose up -d 过程 访问网址&#xff0c;存在页面说明接口存在且存在反序列化漏洞 http://8.130.17.222:8080/invoker/JMXInvokerServlet 2.下载 ysoserial ⼯具进⾏漏洞利⽤…...

2025年优化算法:龙卷风优化算法(Tornado optimizer with Coriolis force,TOC)

龙卷风优化算法&#xff08;Tornado optimizer with Coriolis force&#xff09;是发表在中科院二区期刊“ARTIFICIAL INTELLIGENCE REVIEW”&#xff08;IF&#xff1a;11.7&#xff09;的2025年智能优化算法 01.引言 当自然界的狂暴之力&#xff0c;化身数字世界的智慧引擎&…...

3.24-3 接口测试断言

一.postman 断言 1.断言再test中 #状态码是否等于200 tests["Status code is 200"] responseCode.code 200; #断言响应时间小于200ms tests["Response time is less than 200ms"] responseTime < 200; #断言响应体包含内容 tests["Body…...

DeepSeek面试——模型架构和主要创新点

本文将介绍DeepSeek的模型架构多头潜在注意力&#xff08;MLA&#xff09;技术&#xff0c;混合专家&#xff08;MoE&#xff09;架构&#xff0c; 无辅助损失负载均衡技术&#xff0c;多Token 预测&#xff08;MTP&#xff09;策略。 一、模型架构 DeepSeek-R1的基本架构沿用…...

【PostgreSQL】pg各版本选用取舍逻辑与docker安装postgres:15

企业常用 PostgreSQL 版本推荐 1. PostgreSQL 14&#xff08;最常见&#xff0c;稳定&#xff09; 目前许多企业仍在使用 PostgreSQL 14&#xff0c;因为它在性能、并发处理、JSON 支持等方面做了较多优化&#xff0c;同时又非常稳定。官方支持时间&#xff1a;2026 年 11 月…...

Python----计算机视觉处理(Opencv:图像亮度变换)

一、图像亮度变换 亮度调整&#xff1a;图像像素强度整体变高或者变低。 对比度调整&#xff1a;图像暗处像素强度变低&#xff0c;图像亮处像素强度变高&#xff0c;从而拉大中间某个区域范围的显示精 度。 A&#xff1a;原图 …...

无人机动平衡-如何在螺旋桨上添加或移除材料

平衡无人机螺旋桨是一项精细的工作&#xff0c;直接影响飞行稳定性和组件寿命。不同的方法适用于不同的情况&#xff0c;螺旋桨的材料和尺寸以及所需调整的幅度都会影响选择的方法。 本文将深入探讨添加如胶水和胶带等材料的方法&#xff0c;以及通过打磨和修剪来移除质量的方…...

基于python的租房网站-房屋出租租赁系统(python+django+vue)源码+运行步骤

该项目是基于python/django/vue开发的房屋租赁系统/租房平台&#xff0c;作为本学期的课程作业作品。欢迎大家提出宝贵建议。给师弟开发的课程作业&#xff0c;技术学习可以留言哦 功能介绍 平台采用B/S结构&#xff0c;后端采用主流的PythonDjango进行开发&#xff0c;前端采…...

C++ 的 if-constexpr

1 if-constexpr 语法 1.1 基本语法 ​ if-constexpr 语法是 C 17 引入的新语法特性&#xff0c;也被称为常量 if 表达式或静态 if&#xff08;static if&#xff09;。引入这个语言特性的目的是将 C 在编译期计算和求值的能力进一步扩展&#xff0c;更方便地实现编译期的分支…...

涨薪技术|k8s设计原理

01k8s介绍 Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化 工作负载和服务&#xff0c;有助于实现声明性配置和自动化。它有一个庞大、快速增长的生态系统。Kubernetes 服务、支持和工具广泛可用。Kubernetes 这个名字起源于希腊语&#xff0c;意思是舵…...

基于FPGA的16QAM+帧同步系统verilog开发,包含testbench,高斯信道,误码统计,可设置SNR

目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 16QAM调制解调原理 2.2 帧同步 3.Verilog核心程序 4.完整算法代码文件获得 1.算法仿真效果 vivado2019.2仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 设置SNR12db 将FPGA数据导入到MATLAB显…...

QuecPython 外设接口之GPIO应用指南

基础知识 了解GPIO基础知识更有益于我们使用它。 框图 GPIO&#xff08;通用输入输出&#xff09;是指一种通用的数字输入/输出接口&#xff0c;用于与外部电子元件或设备进行通信。它通常存在于微处理器、微控制器和其他嵌入式系统中。 物理电路结构如下图所示&#xff1a…...

Spring Boot 整合 Nacos 注册中心终极指南

在微服务架构中&#xff0c;配置管理和动态路由是核心需求。Nacos 作为阿里巴巴开源的动态服务发现、配置管理和服务管理平台&#xff0c;能够帮助开发者实现配置热更新、多环境共享配置以及动态路由管理。本文将结合 Spring Boot 和 Spring Cloud Gateway&#xff0c;手把手教…...

清晰易懂的 Maven 彻底卸载与清理教程

一、Windows 系统卸载 Maven 步骤 1&#xff1a;删除 Maven 安装目录 找到 Maven 的安装路径&#xff08;默认可能为 C:\Program Files\apache-maven-3.x.x 或自定义路径&#xff09;。直接删除整个 Maven 文件夹&#xff08;如 apache-maven-3.x.x&#xff09;。 步骤 2&am…...

光流 | 基于KLT算法的人脸检测与跟踪原理及公式,算法改进,matlab代码

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 人脸检测与跟踪 一、KLT算法原理与分析1. 核心思想2. 数学模型二、人脸…...

Spring MVC请求与响应全解析:从参数绑定到异常处理

文章目录 一、请求映射的艺术&#xff1a;RequestMapping深度解析1. 多级路径配置2. 六大核心属性3. RESTful风格实践 二、参数绑定黑科技1. 智能绑定机制基础类型绑定对象嵌套绑定集合类型绑定 2. 参数处理三剑客 三、响应处理全攻略1. 视图跳转三种模式2. JSON交互实践 四、文…...

用免费的github的key调用gpt实现一个简单的rag自动打分评测系统,不用任何框架

1.环境准备 !pip install pymupdf numpy openai 2.导入依赖 import fitz import os import numpy as np import json from openai import OpenAI 3.pdf提取文本 def extract_text_from_pdf(pdf_path):"""从 PDF 文件中提取文本内容。参数:pdf_path (str): …...

SQLServer列转行操作及union all用法

1.创建测试表及数据sql如下 create table ScoresTable( Name varchar(50), ChineseScore int, MathScore int ) insert into ScoresTable values(小张,90,95) insert into ScoresTable values(小王,98,99) 2.表中查询结果如下 3.现需列转行显示&#xff0c;每行显示 姓名…...

深度学习框架PyTorch——从入门到精通(6.2)自动微分机制

本节自动微分机制是上一节自动微分的扩展内容 自动微分是如何记录运算历史的保存张量 非可微函数的梯度在本地设置禁用梯度计算设置requires_grad梯度模式&#xff08;Grad Modes&#xff09;默认模式&#xff08;梯度模式&#xff09;无梯度模式推理模式评估模式&#xff08;n…...