C语言如何通过分治法降低递归深度?

摘要:起因 C++14 引入 STL 的 make_index_sequence 可以生成一个类型为 std::size_t,0 到 N-1 的编译期序列,我们可以这样使用它: 代码 利用函数参数推导提取序
起因 C++14 引入 STL 的 make_index_sequence 可以生成一个类型为 std::size_t,0 到 N-1 的编译期序列,我们可以这样使用它: 代码 //利用函数参数推导提取序列 template<std::size_t... Seq> void foo(std::index_sequence<Seq...>) { //使用Seq } //利用模板特化提取序列 template<typename> struct extract_sequence; template<std::size_t... Seq> struct extract_sequence<std::index_sequence<Seq...>> { //使用Seq }; foo(std::make_index_sequence<5>{});//foo内部得到 {0, 1, 2, 3, 4} extract_sequence<std::make_index_sequence<3>>;//extract_sequence内部得到 {0, 1, 2} 可是在我的程序中,我想创建一个等差数列,std::make_index_sequence 无法直接拿来使用(其实可以间接使用,后文会提到)。于是我编写了一个自己的版本: 代码 //主模板,递归实例化 template<std::size_t Base,std::size_t Step, std::size_t Count, std::size_t... Seq> struct make_arithmetic_progression : make_arithmetic_progression<Base + Step, Step, Count-1, Seq..., Base> { }; //递归终点特化版本 template<std::size_t Base, std::size_t Step, std::size_t... Seq> struct make_arithmetic_progression<Base, Step, 0, Seq...> { using type = std::index_sequence<Seq...>; }; template<std::size_t Base, std::size_t Step, std::size_t Count> using arithmetic_progression = typename make_arithmetic_progression<Base, Step, Count>::type; foo(arithmetic_progression<1, 2, 3>{});//foo内部得到 {1, 3, 5} extract_sequence<arithmetic_progression<3, 3, 3>>;//extract_sequence内部得到 {3, 6, 9} 问题 这个实现看起来没什么问题,可以正确地生成任意指定的等差数列。但是在一个偶然的情况下,我在创建一个很长的数列时,遇到以下错误: 模板递归实例化深度超过限制了,查阅了一下资料,获知各家编译器都对这个深度有一个默认限制,GCC 和 clang 都是 1024,MSVC 是 499。 可以使用编译参数来指定这个限制: 代码 -ftemplate-depth=N //GCC 和 clang /Zc:templateDepth=N //MSVC 但这显然是下策,每次编译这个模板都需要在编译时加上额外的指令,非常麻烦。 解决 自定义方式 我们知道有个排序算法叫归并排序,将长列表不断拆分成最小单元后合并。
阅读全文