Reputation: 11439
I was trying out something simple like this:
template<class T>
array insertionSort(array<T> arr) {
for (int index = 1; index < arr.size(); index++) {
for (int insertion = index; insertion > 0 && array[insertion - 1] > array[insertion]; insertion--) {
std::swap(array[insertion - 1], array[insertion]);
}
}
return arr;
}
void main() {
array<int, 10> mine = { 1, 0, 2, 9, 3, 8, 4, 7, 5, 6 };
array result = insertionSort<int>(mine);
cin.get();
}
It seems as though array requires two type parameters (the type
as well as the size
), so how do I pass it to and from a function without knowing the size up front?
Upvotes: 8
Views: 5061
Reputation: 153830
In general, you don't really want to pass containers around! The same algorithm which works for std::array<T, N>
also works for other data structures, e.g., std::vector<T>
or std::deque<T>
. The C++ approach in that case is to pass iterator and to [slightly] adjust the algorithm:
template<typename BidrectionalIterator>
void insertionSort(BidirectionalIterator begin, BidirectionalIterator end) {
for (BidirectionalIterator it(begin); it != end; ++it) {
for (BidirectionalIterator insertion(it), tmp(insertion);
begin != insertion && *--tmp > *insertion; --insertion) {
std::swap(*tmp, *insertion);
}
}
}
(I didn't verify that the algorithm actually works but you get the idea).
Note that the algorithm deliberately sorts the sequence in-place! If you want to create a sorted copy, create the copy and sort that: this way you have the choice to do it in-place or not rather than being forced to use an approach which may require excessive memory (OK, when the sequence is large you surely don't want to use this algorithm but that's a separate question).
Upvotes: 20
Reputation:
IMO, you should just pass the size as a template parameter and use it in the loop instead of arr.size():
template<class T, size_t size>
array<T, size> insertionSort(array<T> arr) {
for (int index = 1; index < size; index++) {
for (int insertion = index; insertion > 0 && array[insertion - 1] > array[insertion]; insertion--) {
std::swap(array[insertion - 1], array[insertion]);
}
}
return arr;
}
void main() {
array<int, 10> mine; mine.fill(0);
array<int, mine.size()> result = insertionSort<int, mine.size()>(mine);
cin.get();
}
Upvotes: 3
Reputation: 473427
It works the same way as passing the object without knowing the type up front. You use a template parameter:
template<class T, size_t arrSize>
std::array<T, arrSize> insertionSort(std::array<T, arrSize> arr) {
for (int index = 1; index < arrSize; index++) {
for (int insertion = index; insertion > 0 && array[insertion - 1] > array[insertion]; insertion--) {
std::swap(array[insertion - 1], array[insertion]);
}
}
return arr;
}
Upvotes: 10