第十七章:Future Directions_《C++ Templates》notes

Future Directions

        • 核心重难点:
        • 示例代码:
      • 设计题
        • 多选题答案
        • 设计题详解


核心重难点:
  1. 泛型非类型模板参数

    • 允许任意类型作为非类型模板参数(如template<typename T, auto N>
    • 需解决类型推导和链接问题
  2. 编译期控制流

    • constexpr if替代模板偏特化(减少代码膨胀)
    • 折叠表达式优化可变参数模板处理
  3. 反射与元编程增强

    • 类型检查(is_convertible_v等)
    • 反射提案(如成员变量/函数查询)
  4. 模块化支持

    • 解决传统头文件包含模型的编译效率问题
    • 显式实例化与模块接口的交互
  5. 语法简化

    • 放宽typename使用限制
    • void类型规范化(统一处理无返回值函数)

Concepts(概念)
功能:通过显式约束模板参数类型,提升编译时类型检查和错误提示的可读性。

示例代码:
#include <iostream>
#include <vector>
#include <concepts>// 定义一个Concept,要求类型支持加法运算
template<typename T>
concept Addable = requires(T a, T b) {{ a + b } -> std::same_as<T>;
};// 使用Concept约束模板参数
template<Addable T>
T add(T a, T b) {return a + b;
}int main() {std::cout << add(1, 2) << std::endl;          // 输出3(int满足Addable)std::cout << add(1.5, 2.5) << std::endl;      // 输出4(double满足Addable)// std::vector<int>不满足Addable(无operator+),编译报错// std::cout << add(std::vector<int>{1}, std::vector<int>{2}) << std::endl;return 0;
}

编译命令(需支持C++20):

g++ -std=c++20 concepts.cpp -o concepts

Modules(模块)
功能:替代传统头文件,提升编译速度和封装性。

示例代码:
math_module.ixx(模块接口文件):

export module math;export template<typename T>
T add(T a, T b) {return a + b;
}

main.cpp(使用模块):

import math;int main() {std::cout << add(3, 5) << std::endl;  // 输出8return 0;
}

编译命令(需支持C++20模块):

g++ -std=c++20 -fmodules-ts -c math_module.ixx -o math_module.o
g++ -std=c++20 -fmodules-ts main.cpp math_module.o -o main

17.6 Deduction for Nonfinal Pack Expansions(非终结包展开推导)
功能:允许在模板参数包展开时进行类型推导。

示例代码:

#include <iostream>
#include <tuple>// 推导包展开中的类型
template<typename... Ts>
auto make_tuple_and_print(Ts&&... args) {auto t = std::make_tuple(std::forward<Ts>(args)...);std::cout << "Tuple elements: ";((std::cout << args << " "), ...);std::cout << std::endl;return t;
}int main() {auto t = make_tuple_and_print(1, 2.5, "Hello");// 输出类型:std::tuple<int, double, const char*>return 0;
}

编译命令

g++ -std=c++20 pack_deduction.cpp -o pack_deduction

关键知识点总结

特性核心优势典型应用场景
Concepts显式约束模板参数,增强编译错误信息泛型算法、类型安全检查
Modules替代头文件,避免宏污染,提升编译速度大型项目模块化管理
包展开推导简化变长模板参数处理,支持复杂类型构造元编程、通用容器实现

扩展练习
尝试实现一个使用Concepts约束的Comparable概念,并编写一个通用的比较函数模板:

#include <iostream>
#include <concepts>template<typename T>
concept Comparable = requires(T a, T b) {{ a == b } -> std::convertible_to<bool>;{ a != b } -> std::convertible_to<bool>;
};template<Comparable T>
bool safe_compare(const T& a, const T& b) {return a == b;
}int main() {std::cout << std::boolalpha;std::cout << safe_compare(10, 20) << std::endl;       // 输出falsestd::cout << safe_compare(std::string("Hello"), std::string("World")) << std::endl;  // 输出false// std::vector<int>无法比较,编译报错// safe_compare(std::vector<int>{1}, std::vector<int>{2});return 0;
}

多选题

题目1:关于C++20 concept的描述正确的是?
A. 必须在模板参数列表中使用requires子句
B. 可以定义默认约束条件
C. 支持逻辑运算符组合约束
D. 能够自动推导约束条件


题目2:constexpr if与普通if的关键区别是?
A. 编译期求值条件
B. 支持非布尔类型条件
C. 分支代码生成策略不同
D. 可以出现在类外定义

答案:A、C

解析:

  • A正确:条件在编译期求值
  • C正确:不满足条件的分支会被丢弃(SFINAE)
  • B错误:必须为布尔常量表达式
  • D错误:仅限函数作用域

题目3:泛型lambda的捕获列表中可以出现?
A. auto类型占位符
B. 静态成员变量
C. 非静态成员函数指针
D. 模板参数包

答案:B、C

解析:

  • B正确:可以捕获静态成员(如[=] { return MyClass::value; }
  • C正确:可以捕获成员函数指针(如[&f] { return obj.*f(); }
  • A错误:捕获列表不支持auto
  • D错误:模板参数包无法直接捕获

题目4:关于折叠表达式的错误说法是?
A. 支持所有二元操作符
B. 可以展开参数包到逗号表达式
C. 空包展开有明确定义
D. 左右折叠优先级相同

答案:A、D

解析:

  • A错误:不支持||, &&, ,以外的操作符需要括号包裹
  • D错误:左折叠(args + ...)和右折叠(... + args)优先级不同
  • B正确:可以展开到逗号表达式(如([](auto x){}, ...)
  • C正确:空包左折叠为identity,右折叠为identity

题目5:C++23中std::type_identity_t的主要用途是?
A. 禁止类型推导
B. 强制类型转换
C. 消除ADL影响
D. 延迟模板实例化

答案:A、C

解析:

  • A正确:std::type_identity_t<T>阻止T被推导(如decltype(auto) = std::type_identity_t<int>{}
  • C正确:消除ADL查找(如std::type_identity_t<decltype(f)>::type
  • B错误:不改变类型本质
  • D错误:不影响实例化时机

题目6:关于模块化的正确说法是?
A. 模块接口单元必须使用export关键字
B. 模块实现单元可以包含#include指令
C. 模块可以导出宏定义
D. 模块编译单元之间自动处理依赖关系

答案:A、D

解析:

  • A正确:模块接口需显式导出实体(如export module M; export int f();
  • D正确:模块编译器自动管理依赖传递
  • B错误:实现单元不应包含#include
  • C错误:宏无法跨模块可见

题目7:C++20 requires子句可以用于?
A. 函数模板约束
B. 类模板约束
C. 变量模板约束
D. 构造函数约束

答案:A、B、C、D

解析:

  • 所有选项均正确:requires可用于任何模板声明的约束(如template<typename T> requires C<T> class C {};

题目8:关于[[nodiscard]]属性的模板化用法正确的是?
A. 可以作用于类模板
B. 可以作用于函数模板
C. 可以作用于变量模板
D. 无法作用于成员模板

答案:A、B、C

解析:

  • A正确:[[nodiscard]] struct S {};
  • B正确:[[nodiscard]] template<typename T> T f();
  • C正确:[[nodiscard]] template<typename T> T x;
  • D错误:成员模板同样可以标记(如class C { [[nodiscard]] T f(); };

题目9:C++23中std::is_constant_evaluated()的典型应用场景是?
A. 禁止编译期计算
B. 优化运行时分支
C. 实现编译期调试输出
D. 检测异常安全等级

答案:B、C

解析:

  • B正确:避免编译期不必要的开销(如if (!std::is_constant_evaluated()) { /* runtime code */ }
  • C正确:在编译期执行日志输出(需配合if constexpr
  • A错误:无法禁止编译期计算
  • D错误:与异常安全无关

题目10:关于std::format与模板的结合错误说法是?
A. 可以格式化任意类型(需自定义formatter
B. 支持编译期字符串检查
C. 自动推导格式说明符
D. 比printf更易出错

答案:C、D

解析:

  • C错误:需显式指定格式说明符(如std::format("{:.2f}", 3.1415)
  • D错误:类型安全优于printf
  • A正确:通过ADL注册自定义格式化器
  • B正确:constexpr上下文支持编译期检查

设计题

题目1:实现一个支持编译期字符串拼接的concat模板

#include <iostream>
#include <string_view>template<std::size_t N, std::size_t M>
constexpr auto concat(const char(&a)[N], const char(&b)[M]) {std::array<char, N + M - 1> result{};std::copy_n(a, N-1, result.begin());std::copy_n(b, M, result.begin() + N - 1);return result;
}int main() {constexpr auto str = concat("Hello", " World!");static_assert(str == "Hello World!");std::cout << str.data() << std::endl;
}

题目2:使用constexpr if优化斐波那契数列计算

#include <iostream>template<int N>
constexpr int fib() {if constexpr (N <= 1) return N;return fib<N-1>() + fib<N-2>();
}int main() {static_assert(fib<10>() == 55);std::cout << "Fibonacci(10): " << fib<10>() << std::endl;
}

题目3:实现类型安全的变长参数包装器

#include <tuple>
#include <iostream>template<typename... Args>
void log(Args&&... args) {((std::cout << std::forward<Args>(args) << " "), ...);std::cout << std::endl;
}int main() {log("Hello", 42, 3.14, std::string("World"));
}

题目4:基于std::variant的类型安全访问器

#include <variant>
#include <iostream>
#include <string>template<typename... Ts>
struct overloaded : Ts... { using Ts::operator()...; };
template<typename... Ts> overloaded(Ts...) -> overloaded<Ts...>;int main() {std::variant<int, std::string> v = "Hello";std::visit(overloaded{[](int i) { std::cout << "int: "<< i << std::endl; },[](const std::string& s) { std::cout << "string: "<< s << std::endl; }}, v);
}

题目5:编译期素数检测

#include <iostream>
#include <bit>template<unsigned N, unsigned D>
struct is_prime_helper {static constexpr bool value = (N % D != 0) && is_prime_helper<N, D-1>::value;
};template<unsigned N>
struct is_prime_helper<N, 1> {static constexpr bool value = true;
};template<unsigned N>
constexpr bool is_prime() {if constexpr (N < 2) return false;return is_prime_helper<N, N/2>::value;
}int main() {static_assert(is_prime<7>());static_assert(!is_prime<9>());std::cout << "Is 13 prime? " << std::boolalpha << is_prime<13>() << std::endl;
}

多选题答案
  1. 答案:B、C

解析:

  • B正确:concept可以定义默认约束(如template<typename T> concept C = ...
  • C正确:支持&&, ||, !组合约束(如C1 && !C2)
  • A错误:C++20允许隐式约束(无需requires
  • D错误:约束需显式声明
  1. 答案:A、C

    • constexpr if在编译期求值条件并丢弃不满足的分支
  2. 答案:B、C

    • 泛型lambda可捕获静态成员和成员函数指针
  3. 答案:A、D

    • 折叠表达式不支持所有操作符且左右折叠优先级不同
  4. 答案:A、C

    • std::type_identity_t阻止类型推导并消除ADL影响
  5. 答案:A、D

    • 模块需显式导出实体且自动处理依赖关系
  6. 答案:A、B、C、D

    • requires可约束所有模板类型
  7. 答案:A、B、C

    • [[nodiscard]]可修饰类/函数/变量模板
  8. 答案:B、C

    • std::is_constant_evaluated()优化运行时分支和调试输出
  9. 答案:C、D

    • std::format需显式指定格式且比printf更安全
设计题详解
  1. 编译期字符串拼接

    • 使用std::array存储结果,递归拼接字符数组
  2. 斐波那契数列优化

    • constexpr if终止递归条件,避免无限展开
  3. 变长参数包装器

    • 折叠表达式展开参数包,完美转发所有参数
  4. 类型安全访问器

    • std::visit结合overloaded实现多态访问逻辑
  5. 编译期素数检测

    • 递归模板实现试除法,std::bit辅助优化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38060.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue 中的日期格式化实践:从原生 Date 到可视化展示!!!

&#x1f4c5; Vue 中的日期格式化实践&#xff1a;从原生 Date 到可视化展示 &#x1f680; 在数据可视化场景中&#xff0c;日期时间的格式化显示是一个高频需求。本文将以一个邀请码关系树组件为例&#xff0c;深入解析 Vue 中日期格式化的 核心方法、性能优化 和 最佳实践…

C语言的数据类型与变量(完整版)

目录 一、基本数据类型 &#xff08;一&#xff09;字符类型 &#xff08;二&#xff09;整数类型 1、短整型 — short 2、整型 — int 3、长整型 — long 4、长长整型 — long long &#xff08;三&#xff09;布尔类型 &#xff08;四&#xff09;浮点类型 1、单精…

免费下载 | 2025低空经济产业发展报告

低空经济概览 产业链条&#xff1a;低空经济产业链分为上游的低空经济基础设施&#xff08;如空管系统、飞行基地等&#xff09;、中游的低空制造&#xff08;包括无人机、eVTOL、直升机等飞行器的设计、研发、生产&#xff09;和下游的低空运营及飞行服务。低空经济以低空空域…

git_version_control_proper_practice

git_version_control_proper_practice version control&#xff0c;版本控制的方法之一就是打tag 因为多人协作的项目团队&#xff0c;commit很多&#xff0c;所以需要给重要的commit打tag&#xff0c;方便checkout&#xff0c;检出这个tag 参考行业的实践方式。如图git、linux…

金桔网桥连载4-详解

上一节我讲到小王升职加薪&#xff0c;越活越年轻&#xff0c;然后我们的网络就成这样的 如果继续往下进行网络扩展&#xff0c;恐怕看的人就越看越糊涂&#xff0c;如果一篇文章看到人越少&#xff0c;那么存在的价值越小&#xff0c;使我想起了每年一部的梦工厂电影&#xff…

从GTC2025首次量子日看英伟达量子AI融合算力网络前景与趋势

GTC2025 Quantum Day 最新内容全部汇总: 技术名称描述合作伙伴/开发者应用场景/目标量子模拟器优化方案NVIDIA与IonQ、D-Wave合作,针对量子模拟器进行性能优化,提升量子计算任务效率。IonQ、D-Wave量子算法开发、复杂系统模拟混合量子-经典计算架构结合量子计算与经典GPU加速…

24.map和set的使用

一、序列式容器和关联式容器 序列式容器&#xff1a;逻辑结构为线性序列的容器&#xff0c;两个位置所存放的数据一般没有紧密关系&#xff0c;例如两个位置交换一下&#xff0c;逻辑结构没有改变。 关联式容器&#xff1a;通常是非线性结构&#xff08;堆例外&#xff09;&…

免费Typora1.8.6安装教程

&#x1f31f; Typora - 极简主义的 Markdown 编辑器免费指南 &#x1f31f; &#x1f4cc; 什么是 Typora&#xff1f; Typora 是一款广受好评的 **所见即所得** 的 Markdown 编辑器&#xff0c;以极致简洁的界面和流畅的写作体验闻名。它让 Markdown 写作变得像使用 Word 一…

元音辅音及其字母组合发音

文章目录 单元音长元音/ɑː//ɔ://u://i://ɜː/// 短元音/ʌ//ɒ//ʊ//ɪ//ə//e/ 双元音/eɪ//aɪ//ɔɪ//ɪə//eə//ʊə//əʊ//aʊ/ 辅音3个鼻辅音m n ŋ 5个独立浊辅音w j r l h 20个清浊相对的辅音s zʃ ʒf vθ p bt dk gts dztʃ dʒtr dr 以下是列举的部分字母组合…

基于FPGA频率、幅度、相位可调的任意函数发生器(DDS)实现

基于FPGA实现频率、幅度、相位可调的DDS 1 摘要 直接数字合成器( DDS ) 是一种通过生成数字形式的时变信号并进行数模转换来产生模拟波形(通常为正弦波)的方法,它通过数字方式直接合成信号,而不是通过模拟信号生成技术。DDS主要被应用于信号生成、通信系统中的本振、函…

C++调用ffmpeg解复用、解码案例

框架 一个封装文件&#xff08;mp4&#xff09;如何播放&#xff1f;大体流程如下&#xff1a; 案例 本案例实现在windows环境下&#xff0c;调用ffmpeg4.4.5动态库实现上述从解封装、视频解码、音频解码的全部过程&#xff0c;案例测试通过。由于ffmpeg接口功能网上资料较多&a…

Linux(进程)

一.冯诺依曼体系结构 输入设备&#xff1a;键盘&#xff0c;鼠标&#xff0c;话筒&#xff0c;摄像头...网卡&#xff0c;磁盘 输出设备&#xff1a;显示器&#xff0c;磁盘&#xff0c;网卡&#xff0c;打印机 外设&#xff1a;输入设备输出设备 cpu&#xff08;中央处理器&am…

[极客大挑战 2019]BabySQL—3.20BUUCTF练习day4(3)

[极客大挑战 2019]BabySQL-3.20BUUCTF练习day4(3) 做题过程 打开是以下页面&#xff08;前几天有它的第一版和第二版出现&#xff09;输入1’ 回显以下内容&#xff08;还是字符型以单引号闭合&#xff0c;因为有报错信息回显&#xff09; 输入1 order by 4%23回显成这个 被过…

[Effective C++]条款20:宁以 pass-by-reference-to-const替换 pass-by-value

. 在C中&#xff0c;函数参数与返回值的数据传递的方式&#xff0c;对程序的性能和正确性有着重要影响。C默认使用pass-by-value&#xff08;传值&#xff09;的方式传递参数。但这种方式在某些情况下会导致性能问题和对象切割问题。 C推荐使用pass-by-reference-to-const&…

文字变央视级语音转换工具

大家在制作短视频、广告宣传、有声读物、自媒体配音、学习辅助等场景的时候&#xff0c;经常会需要用到配音来增强视频的表现力和吸引力。然而&#xff0c;市面上的一些配音软件往往需要收费&#xff0c;这对于很多初学者或者预算有限的朋友来说&#xff0c;无疑增加了一定的负…

邂逅书香:在诗韵与青春中找寻心灵归处

在信息如洪流般奔涌的当下&#xff0c;我们的灵魂时常在喧嚣中漂泊&#xff0c;渴望一处宁静港湾。而书籍&#xff0c;一直以来都是人类最忠诚的精神伴侣。今天&#xff0c;要为诗歌爱好者和青春文学迷们带来两份特别的礼物——《韵之队诗集》与《青春与爱共舞》&#xff0c;它…

国科大——计网(0812)——实验作业

**前沿&#xff1a;**此博客记录了24—25年度秋季学期计算机网络&#xff08;0812&#xff09;课程的实验作业&#xff0c;所提供的材料仅供参考。 0 实验题目 本次实验总共提供了四个可选的题目&#xff0c;即BGP分析实验&#xff0c;BGP 前缀劫持攻击及检测实验&#xff0c…

新能源汽车高压液体加热器总成技术解析及未来发展趋势

引言 新能源汽车的快速发展对热管理系统提出了更高要求&#xff0c;高压液体加热器作为核心组件&#xff0c;直接影响车辆低温性能、电池寿命及用户体验。本文以实际产品为例&#xff0c;结合行业数据与技术趋势&#xff0c;深度解析高压液体加热器的技术原理、市场现状及未来…

蓝桥杯 数字接龙

问题描述 小蓝最近迷上了一款名为《数字接龙》的迷宫游戏。 游戏在一个大小为 N N 的格子棋盘上展开&#xff0c;其中每一个格子处都有一个 0 到 K-1 之间的整数。 游戏规则如下&#xff1a; 从左上角 (0, 0) 出发&#xff0c;目标是到达右下角 (N-1, N-1)。 每一步可以选…

SysVinit和Systemd的系统运行级别

Linux运行级别 SysVinit系统(init守护进程)Linux系统运行级别SysVinit系统(init守护进程)查看Linux运行级别SysVinit系统(init守护进程)修改运行级别&#xff1a; Systemd守护进程Linux系统运行级别systemd查看运行级别Systemd查看系统当前运行级别 systemd修改运行级别multi-u…