我正在尝试实现Merge排序算法:
#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;
}
此程序无法编译:
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
我知道我在宣言中搞砸了一些简单的东西,但我无法理解。
答案 0 :(得分:12)
TObject
中的std::function<bool(TObject const&, TObject const&)>
无法从任何非std::function
的参数中推断出来,请参阅this question。
您还在滥用std::function
- 只有在您想存储任何可调用实体时才使用它。如果您只想将任何可调用的参数作为参数,请将其设为模板参数:
template<class Iter, class Comp>
void mergeSort(Iter first, Iter last, Comp comp)
{
// use 'comp(a, b)'
}
这也是stdlib做的方式(实际上看到每个带谓词的算法,如std::sort
)。这样,您还可以避免std::function
执行的(在您的情况下不必要)类型擦除。
答案 1 :(得分:5)
你可以看看std :: sort:
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
http://en.cppreference.com/w/cpp/algorithm/sort
这样你可以使用你想要的任何可调用的东西。
答案 2 :(得分:2)
您的功能compare
不是std::function
,而您的mergeSort
需要一个。
此外,你应该不将const_iterator
传递给你的函数,因为它应该修改数组。
如果您更改了代码并使用此代码:
std::function<bool(const int&, const int&)> myCompare = compare;
mergeSort(container.begin(), container.end(), myCompare);
它有效(见http://ideone.com/7FdKTP)。
在我看来,将比较器实现为operator()
的结构更容易。这样,您传递的是对象而不是函数,这更容易管理。
答案 3 :(得分:1)
虽然我不知道如何完全解决这个问题,但很明显,编译器无法推断出这些论点。明确说明它们可以作为一种解决方法:
mergeSort< std::list<int>::iterator, bool >(container.begin(), container.end(), compare);
另一种方法是将您传递的函数显式转换为std::function
。
你也可以通过将最后一个参数设为operator<
而不是比较函数来实现这一点,我认为这更直观。
答案 4 :(得分:-1)
mergeSort
期待const TIterator
而您的人不在。