How to use std::sort with an std::array?

300 Views Asked by At

I need to sort an std::array, but I can't figure out how to do that using the std::sort() function, since I get the errors "no instance of overloaded function sort matches the argument list" and "no operator '+' matches these operands". When I use the same syntax to try to sort a regular array, I have no errors. Here is code which produces the problem:

#include <algorithm>
#include <array>

int nums[5] = {1, 2, 3, 4, 5};
std::array<int, 5> morenums = {1, 2, 3, 4, 5};


int main(){
    std::sort(nums, nums + 5);//no error
    std::sort(morenums, morenums + 5);//error    
}

I was trying to use the std::sort() method to sort an std::array, but I couldn't figure out how to do this, since I kept getting errors.

2

There are 2 best solutions below

0
HolyBlackCat On BEST ANSWER

Same as you would sort any other container, such as std::vector:

std::sort(morenums.begin(), morenums.end());

It's the plain arrays that have the odd syntax, not std::array.

You can also do std::sort(std::begin(morenums), std::end(morenums)); or std::ranges::sort(morenums);, those work for both plain arrays and containers.

3
Joel On

std::sort() and in fact many other algorithms in the STL make use of iterators. Iterators are classes which you can at least dereference (*) and increment(++) and they usually point to an element in a range of elements. They can point to invalid elements, such as the .end() method of e.g. a std::array or other STL containers (which points to the element after the last valid element).

The most basic form of an iterator is a raw pointer, which supports increment, dereference and also pointer arithmetic which you made use of. In your example int nums[5] is just a c-style array, which can decay into a pointer to its first element.

Therefore std::sort(nums, nums + 5) does the same as std::sort(&nums[0], &nums[5]) would do, with nums[5] being one element to far, but that is ok since it will not get dereferenced and is just what std::sort() expects.

However std::sort(morenums, morenums + 5) does not work, since morenums is a normal class (not an iterator), doesn't decay into a pointer and you can't do addition with it. However std::array comes with the methods .begin() and .end(), which return exactly those two iterators (or more complex pointers) you need for std::sort(). .begin() points to the first valid element (morenums[0]) and .end() again to the next element after the last valid one. With use of those iterators you don't need to care about the size of your std::array, as you needed to with the c-style array.

You could use std::sort(&morenums[0], &morenums[0] + morenums.size()) to sort your std::array too, which would use pointers and not the iterator class, but this is just for demonstration and is the same as you did with your c-style array. However you should not use this in real code, rather just use the iterators that come with std::array. This approach with pointers works for std::array, since all elements are in order, each element is just at the next memory location, but it might not work for other containers which don't store elements in one contiguous block of memory.


To make your example work, you can change the line in which you attempt to sort the std::array to std::sort(morenums.begin(), morenums.end()); and your working code would look like this:

#include <array>
#include <algorithm>

int nums[5] = { 5, 2, 3, 4, 1 };
std::array<int, 5> morenums = { 1, 2, 5, 4, 3 };


int main() {
    std::sort(nums, nums + 5);
    std::sort(morenums.begin(), morenums.end()); 

    return 0;
}