Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly declare a generic sorting algorithm?

I am trying to implement the Merge sort algorithm:

#include <list>
#include <functional>
#include <iterator>
#include <iostream>
#include <random>

template <typename TIterator, typename TObject>
void mergeSort(const TIterator& begin, const TIterator& end,
               std::function<bool (const TObject& left,
                                   const TObject& right)> criterium)
{
    //...
}

bool compare(int a, int b)
{
    return a < b;
}

int main(int argc, char** argv)  // And now to test the algorithm
{
    std::list<int> container;
    for (int i = 0; i < 100; ++i)
        container.push_back(random() % 20);

    mergeSort(container.begin(), container.end(), compare);

    for (auto it = container.begin(); it != container.end(); ++it)
        std::cout << (*it) << std::endl;

    return 0;
}

This program does not compile:

error: no matching function for call to 
mergeSort(std::list<int>::iterator, std::list<int>::iterator, bool (&)(int, int))

candidate is:

template<class TIterator, class TObject> 
void mergeSort(const TIterator&, const TIterator&, 
std::function<bool(const TObject&, const TObject&)>)

at global scope

I know that I messed something simple in my declaration but I cannot figure it out.

like image 901
Martin Drozdik Avatar asked Nov 28 '25 06:11

Martin Drozdik


2 Answers

The TObject in std::function<bool(TObject const&, TObject const&)> can not be deduced from any argument that is not a std::function already, see this question.

You're also misusing std::function - only use it if you want to store any callable entity. If you just want to take anything callable as a parameter, make it a template parameter:

template<class Iter, class Comp>
void mergeSort(Iter first, Iter last, Comp comp)
{
  // use 'comp(a, b)'
}

This is also the way the stdlib does it (see virtually every algorithm with a predicate, like std::sort). This way, you're also avoiding the (in your case unnecessary) type erasure that std::function performs.

like image 198
Xeo Avatar answered Nov 30 '25 21:11

Xeo


You could just take a look at std::sort:

template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );

http://en.cppreference.com/w/cpp/algorithm/sort

This way you can use whatever callable thing you want to.

like image 34
cooky451 Avatar answered Nov 30 '25 19:11

cooky451



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!