更改类型后递归为模板化函数
Recurse into a templated function after changing the type
我目前正在编写自己的合并排序实现以进行实践。合并列表的左侧和右侧部分时,创建仅包含两侧较小部分的临时列表是有意义的。但是,逻辑会根据复制到临时的一侧而变化。
我的函数具有以下签名:
template<class RandomIt, class Compare>
void Merge(RandomIt begin, RandomIt middle, RandomIt end, Compare Comp);
我有一个聪明的想法,在开始时检查[begin,middle)
和[middle,end)
的长度,如果左边更大,则将迭代器转换为反向迭代器并递归调用该函数。喜欢这个:
template<class RandomIt, class Compare>
void Merge(RandomIt begin, RandomIt middle, RandomIt end, Compare Comp) {
size_t leftLength = std::distance(begin, middle);
size_t rightLength = std::distance(middle, end);
if (leftLength > rightLength) {
using ReverseIterator = std::reverse_iterator<RandomIt>;
Merge(ReverseIterator(end), ReverseIterator(std::next(middle)), ReverseIterator(begin), Comp);
return;
}
//Now [begin,middle) is guaranteed <= [middle,end)
//...
}
但是,编译器给出了一个相当严重的错误。
fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
我在 ideone.com 上创建了一个重现错误的小型独立应用程序。
编辑:对于合并排序,我刚刚意识到这不起作用,因为比较函数需要反转。
这里的问题是,您在递归的每一步都创建了函数Merge
的新实例化,即第一次从randomaccess_iterator
创建reverse_iterator
时。然后编译器从reverse_iterator
创建一个reverse_iterator
,依此类推.....
正如您在创建reverse_iterator
时必须注意到的那样,迭代器的模板类型不断变化。从而创建模板化函数的新实例。
简而言之,您对迭代器的使用是错误的。
这可能有效:
template <class RandomIt, class RevIt>
void Test(RandomIt begin, RandomIt middle, RandomIt end, RevIt rit) {
size_t leftLength = std::distance(begin, middle);
size_t rightLength = std::distance(middle, end);
if (leftLength > rightLength) {
Test(RevIt(end), RevIt(middle), RevIt(begin), rit);
return;
}
}
template <typename RandomIt>
void Test(RandomIt begin, RandomIt middle, RandomIt end) {
Test(begin, middle, end, std::reverse_iterator<RandomIt>());
}
int main() {
std::vector<int> nums = { 2, 1, 123, 1, 23, 123, 123, 5234, 52, 3, 452, 3, 452, 5 };
int middle;
std::cin >> middle;
Test(nums.begin(), nums.begin()+middle, nums.end());
return 0;
}
问题是Merge<it>
需要Merge<std::reverse_iterator<it>>
,这需要Merge<std::reverse_iterator<std::reverse_iterator<it>>
,这需要Merge<std::reverse_iterator<std::reverse_iterator<std::reverse_iterator<it>>>
需要Merge<std::reverse_iterator<std::reverse_iterator<std::reverse_iterator<std::reverse_iterator<it>>>>
,这需要......
因此,您想要的是已经反向迭代器的ReverseIterator(
使用原始迭代器。因此,您需要帮助程序函数:
template <class RandomIt>
RandomIt ReverseIt(std::reverse_iterator<RandomIt> it) {
return it.base();
}
template <class RandomIt>
std::reverse_iterator<RandomIt> ReverseIt(RandomIt it) {
return std::reverse_iterator<RandomIt>(it);
}
template<class RandomIt, class Compare=std::less<typename std::iterator_traits<RandomIt>::value_type>>
void Merge(RandomIt begin, RandomIt middle, RandomIt end, Compare Comp={}) {
size_t leftLength = std::distance(begin, middle);
size_t rightLength = std::distance(middle, end);
if (leftLength > rightLength) {
Merge(ReverseIt(end), ReverseIt(std::next(middle)), ReverseIt(begin), Comp);
return;
}
//Now [begin,middle) is guaranteed <= [middle,end)
//...
}
编译证明:http://coliru.stacked-crooked.com/a/741d73f889594e36
- 递归函数计算序列中的平方和(并输出过程)
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 如何在Elixir中调用递归函数并行
- 递归函数有效,但无法记忆
- 字符串化递归的"std::vector<std::vector<...>>"而不使用部分模板函数专用化
- 为什么我的递归函数按降序打印,然后按升序打印?
- 为什么递归函数的最终输出是 5?
- 有没有办法使用递归函数找到数组中最小值的 INDEX?C++
- 如何将记忆应用于此递归函数?
- 如何从递归函数中完全返回,该函数给出了每个函数结果的累积相加?
- 无穷大而循环时具有递归函数
- 即使没有调用这个递归函数,它是如何工作的?
- 如何使此递归函数从给定的起始位置返回最小的整数?
- 复制构造函数中的递归调用
- 为什么编译器将其解析为函数指针而不是递归调用?
- 此递归函数的每次迭代的值存储在哪里?
- 在 C++14 中使用通用 lambda 函数递归
- 大量函数递归-C++
- 用内部类函数递归地添加数组数
- 函数递归 C++ 的最大数量