面试题答案
一键面试设计思路
- 模板递归:利用模板递归展开一系列编译期操作。在递归过程中,根据不同的模板参数值来决定下一步操作,例如,通过递增或递减模板参数来控制递归深度,进而控制对象成员初始化的顺序或条件。
- SFINAE(Substitution Failure Is Not An Error):通过检测模板实例化过程中是否存在特定的类型或成员,选择性地启用或禁用某些模板特化。这可以用于根据不同的编译期条件,决定对象成员的初始化方式。
- 控制对象成员初始化:将对象成员的初始化逻辑封装在模板类中,利用模板递归和SFINAE来决定哪些成员需要初始化以及如何初始化。例如,可以创建一个模板元函数,它接收对象类型和编译期条件作为参数,根据条件返回不同的初始化策略。
核心代码片段
// 示例类型
struct MyType {
int value;
MyType(int v) : value(v) {}
};
// 模板递归终止条件
template<int N>
struct InitObject {
static void init(MyType& obj) {
InitObject<N - 1>::init(obj);
// 根据N的值执行特定的初始化逻辑
if constexpr (N % 2 == 0) {
obj.value += N;
}
}
};
template<>
struct InitObject<0> {
static void init(MyType& obj) {
// 递归终止,初始值设定
obj.value = 0;
}
};
// SFINAE示例:根据类型特性选择初始化方式
template<typename T, typename = void>
struct InitSelector {
static void init(T& obj) {
// 默认初始化逻辑
obj = T();
}
};
template<typename T>
struct InitSelector<T, std::enable_if_t<std::is_same_v<T, MyType>>> {
static void init(T& obj) {
InitObject<5>::init(obj);
}
};
int main() {
MyType obj;
InitSelector<MyType>::init(obj);
return 0;
}
在上述代码中:
InitObject
模板类通过递归实现了一种编译期的循环,N
作为递归的控制参数。在每次递归中,根据N
的值执行特定的初始化逻辑。InitSelector
模板类利用 SFINAE 技术,根据类型T
是否为MyType
来选择不同的初始化方式。如果是MyType
,则调用InitObject
进行特定初始化;否则执行默认初始化。