Obecnie piszę własną implementację sortowania scalania do praktyki. Podczas łączenia lewej i prawej części listy sensowne jest utworzenie tymczasowej listy z mniejszą z dwóch stron. Logika zmienia się jednak w zależności od strony, która została skopiowana do temp.Powtarzanie w szablonowej funkcji po zmianie typu
Moja funkcja ma następujący podpis:
template<class RandomIt, class Compare>
void Merge(RandomIt begin, RandomIt middle, RandomIt end, Compare Comp);
miałem sprytny pomysł, aby sprawdzić długości [begin,middle)
i [middle,end)
na początku, a jeśli lewy był większy, konwertować iteratory odwrócić iteratory i rekurencyjnie zadzwoń do funkcji. W ten sposób:
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)
//...
}
Jednak kompilator daje dość gruby błąd.
fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
Utworzyłem little stand-alone application on ideone.com że reprodukuje błąd.
EDYCJA: Dla mergesort, właśnie zdałem sobie sprawę, że to nie zadziała, ponieważ funkcja Porównaj musi zostać odwrócona.
Rozumiem, że kompilator przeżywa tego procesu rekurencyjnie dedukowania typów zagnieżdżonych iterator & reverse iteratory. Jest jednak jasne, że głębokość rekurencji nie przekroczy 1. –
"jest jasne, że głębokość rekursji nie przekroczy 1'..to jest stos wywołań środowiska wykonawczego, o którym mówisz, prawda? Nie ma tu przypadku bazowego, aby zatrzymać rekursję szablonu. – Arunmu
Zaktualizowano rozwiązaniem, które może działać. – Arunmu