MST

星途 面试题库

面试题:C++ 泛型编程的元编程优化

在 C++ 元编程中,使用递归模板实例化进行编译期计算是常见的做法。例如计算阶乘。但当计算较大数的阶乘时,递归深度可能导致编译错误。请提出一种优化方案,在保证编译期计算的同时,避免递归深度问题,并编写相应的代码实现。
29.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

优化方案

可以使用模板元编程中的折叠表达式(Fold Expressions)来替代递归模板实例化。折叠表达式可以在编译期展开参数包,从而实现循环效果,避免递归深度问题。

代码实现

#include <iostream>

// 辅助模板,用于展开参数包进行乘法运算
template <typename T, T... Values>
constexpr T product() {
    return (Values *... * 1);
}

// 计算阶乘的模板
template <unsigned int N>
constexpr unsigned int factorial() {
    return product<unsigned int, (N - 1), (N - 2),..., 1>();
}

// 特化模板,处理0!和1!
template <>
constexpr unsigned int factorial<0>() {
    return 1;
}

template <>
constexpr unsigned int factorial<1>() {
    return 1;
}

int main() {
    // 编译期计算5的阶乘
    constexpr unsigned int result = factorial<5>();
    std::cout << "5! = " << result << std::endl;
    return 0;
}

在上述代码中:

  1. product 模板使用折叠表达式 (Values *... * 1) 对参数包 Values 中的所有值进行乘法运算。这里的 *... * 是折叠表达式的语法,它会将参数包中的值按照乘法操作依次展开计算。
  2. factorial 模板利用 product 模板来计算阶乘。通过参数包展开的方式,将 N - 1, N - 2, ..., 1 作为参数传递给 product 模板进行编译期乘法运算。
  3. 针对 factorial<0>factorial<1> 进行特化,以处理边界情况,确保 0!1! 都返回 1

这样,在编译期计算阶乘时,通过折叠表达式避免了递归模板实例化可能导致的递归深度问题。