整本书测试_20道多选+10道设计_《C++ Templates》notes
完整答案, 稍后给出
多选题目
-
关于模板参数类型推导,以下哪些说法正确?
A. 当模板参数作为函数参数按值传递时允许数组到指针的隐式转换
B. 按引用传递的模板参数会保留const限定符
C. 模板参数类型推导不考虑返回类型
D. 显式指定部分模板参数时必须从左到右连续指定 -
关于可变参数模板,正确的是?
A. sizeof…(Args) 可以获取模板参数包的元素数量
B. 折叠表达式仅支持二元运算符
C. 参数包展开时可以使用任意表达式模式
D. 参数包必须在参数列表最右端 -
类模板特化与偏特化的区别在于:
A. 偏特化必须保留至少一个模板参数
B. 全特化需要template<>前缀
C. 偏特化可以针对指针类型
D. 全特化可以修改成员函数的签名 -
关于SFINAE,正确的有?
A. 替换失败不会导致编译错误
B. 只能通过enable_if使用
C. 可用于函数模板重载决议
D. decltype表达式可能触发SFINAE -
类模板参数推导规则:
A. 构造函数参数类型参与推导
B. 用户定义的推导指南优先于自动推导
C. 聚合类模板支持参数推导
D. 推导时忽略隐式转换 -
关于模板元编程,正确的有:
A. constexpr函数可以替代部分模板元编程
B. 类型特征(type traits)依赖模板特化
C. 递归实例化深度受编译器限制
D. 编译时if会阻止模板实例化 -
模板的实例化时机会是:
A. 显式实例化声明时
B. 首次使用时隐式实例化
C. 成员函数只有在被调用时实例化
D. 虚函数模板允许存在 -
关于移动语义与完美转发:
A. 通用引用必须用T&&声明
B. std::forward保持值类别
C. 移动构造函数应声明为noexcept
D. 完美转发需要引用折叠规则 -
关于类型别名,正确的有:
A. using可以定义模板别名
B. typedef支持模板别名
C. 尾置返回类型使用类型推导
D. _t后缀的类型特征需要显式::type -
模板的ODR规则要求:
A. 跨TU的相同实例化必须一致
B. 显式特化声明必须在使用前可见
C. 内联函数模板允许多次定义
D. 模板参数名称必须相同 -
关于概念(concepts),正确的有:
A. 可以约束模板参数类型
B. requires子句参与重载决议
C. 替代SFINAE的更清晰方式
D. 支持类型特征的逻辑组合 -
模板特化的匹配规则:
A. 偏特化比主模板优先
B. 非模板函数优先于模板
C. 更特殊的模板优先
D. 参数完全匹配优先推导 -
关于可变参数模板展开,正确的是:
A. 可以在using声明中展开
B. 支持嵌套参数包展开
C. 零长度包展开有效
D. 函数参数包必须最后出现 -
模板的编译时计算包括:
A. constexpr变量
B. 模板递归实例化
C. if constexpr条件分支
D. 折叠表达式求值 -
关于模板友元,正确的有:
A. 可以声明模板为友元
B. 友元声明影响ADL查找
C. 特化的友元需要前向声明
D. 友元函数可以定义在类内 -
模板参数类型的有效选项:
A. 包含auto的非类型参数
B. 浮点类型的非类型参数
C. 类类型的非类型参数
D. 字符串字面量的引用参数 -
模板的实例化控制方法:
A. extern模板声明
B. explicit实例化定义
C. inline函数模板
D. 匿名命名空间 -
关于模板参数推导:
A. 转发引用保持值类别
B. 数组参数推导为指针
C. auto类型推导规则相同
D. 显式参数必须完全指定 -
模板元编程的典型应用:
A. 类型特征检查
B. 编译期数值计算
C. 代码生成优化
D. 动态多态实现 -
关于CRTP模式,正确的有:
A. 基类使用派生类作为模板参数
B. 实现静态多态
C. 避免虚函数开销
D. 支持混入接口
答案与解析
-
ABC
A正确(数组退化为指针属于decay);B正确(引用传递保留const);C正确(返回类型不参与推导);D错误(显式参数可间隔指定) -
AC
A正确;B错误(支持一元形式);C正确(如(print(args), …);D错误(包可出现在中间) -
ABCD
所有选项均为模板特化的正确描述 -
ACD
B错误(可用其他方式如返回类型) -
ABCD
全部符合C++17推导规则 -
ABC
D错误(不影响实例化,仅代码排除) -
ABC
D错误(虚函数不能是模板) -
BCD
A错误(需要类型推导上下文) -
AC
B错误(typedef不支持);D错误(_t已处理::type) -
ABC
D错误(参数名不影响ODR) -
ABCD
全部为概念的正确特性 -
ABC
D错误(可能存在类型转换) -
ABC
D错误(函数参数包可非结尾) -
ABCD
全部属于编译时计算手段 -
ABCD
均符合友元模板规则 -
AD
B错误(C++20前不允许);C错误(需literal type) -
AB
C控制链接性;D用于避免符号冲突 -
ABC
D错误(C++17允许部分推导) -
ABC
D属于动态多态范畴 -
ABCD
全部为CRTP的正确描述
10道C++模板高级编程题目
题目1:变参模板求和
要求:使用折叠表达式实现编译时变参模板求和函数,支持整数、浮点数、字符串拼接
题目2:SFINAE类型检查
要求:实现is_iterable
类型特征,检查类型是否支持begin()
和end()
方法
题目3:完美转发工厂
要求:实现通用工厂函数make()
,支持任意参数构造对象并返回shared_ptr
题目4:编译时字符串处理
要求:设计编译时字符串类CompileString
,支持拼接、长度获取和下标访问
题目5:CRTP数学向量
要求:使用CRTP实现数学向量类模板,支持元素级运算符重载
题目6:变参模板索引访问
要求:实现Tuple
类模板及其get<N>()
访问方法,支持编译时类型检查
题目7:类型列表反转
要求:实现编译时类型列表TypeList
及其反转算法Reverse
题目8:条件排序策略
要求:使用模板特化实现排序策略选择(快速排序/冒泡排序),基于类型特征
题目9:多维数组生成器
要求:实现NDArray<N,T>
类模板,生成N维数组并支持编译时维度检查
题目10:异常安全资源管理
要求:设计模板类ScopeGuard
,支持RAII模式和不同清理策略
题目答案与解析
题目1答案:变参模板求和
#include <iostream>
#include <string>
template <typename... Ts>
auto sum(Ts... args) {
return (... + args); // 折叠表达式求和
}
template <typename... Ts>
std::string concat(Ts&&... args) {
return (std::string{} + ... + args); // 字符串拼接
}
int main() {
// 测试整数求和
std::cout << sum(1, 2, 3) << "\n"; // 6
std::cout << sum(1.5, 2.5, 3.5) << "\n"; // 7.5
// 测试字符串拼接
std::cout << concat("Hello", " ", "World") << "\n"; // Hello World
std::cout << concat("C++", " ", "Templates") << "\n"; // C++ Templates
}
题目2答案:SFINAE类型检查
#include <iostream>
#include <type_traits>
#include <vector>
template <typename T, typename = void>
struct is_iterable : std::false_type {};
template <typename T>
struct is_iterable<T, std::void_t<
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())>>
: std::true_type {};
template <typename T>
constexpr bool is_iterable_v = is_iterable<T>::value;
int main() {
std::cout << std::boolalpha;
std::cout << is_iterable_v<std::vector<int>> << "\n"; // true
std::cout << is_iterable_v<int> << "\n"; // false
struct Test { void begin(); void end(); };
std::cout << is_iterable_v<Test> << "\n"; // true
}
题目3答案:完美转发工厂
#include <memory>
template <typename T, typename... Args>
auto make(Args&&... args) {
return std::make_shared<T>(std::forward<Args>(args)...);
}
struct Point {
int x, y;
Point(int a, int b) : x(a), y(b) {}
};
int main() {
auto p = make<Point>(3, 4);
std::cout << p->x << "," << p->y << "\n"; // 3,4
}
测试说明
每个答案包含:
- 关键模板技术实现
- 编译时计算验证
- 多种类型测试用例
- 输出结果验证
通过实现这些题目,可以深入掌握:
- 变参模板展开模式
- SFINAE与类型萃取
- 完美转发机制
- 编译时计算技巧
- CRTP设计模式
- 模板元编程思想
建议按顺序实现并测试每个题目,观察模板实例化过程和编译时行为,结合调试工具验证运行时表现。