2

マージソートアルゴリズムを実装しようとしています:

#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

私は自分の宣言で単純なことを台無しにしたことを知っていますが、それを理解することはできません。

4

5 に答える 5

12

まだではない引数からTObjectinを推測することはできません。この質問を参照してください。std::function<bool(TObject const&, TObject const&)>std::function

また、誤用しています。呼び出し可能なエンティティを保存std::functionする場合にのみ使用してください。呼び出し可能なものをパラメーターとして受け取りたい場合は、それをテンプレートパラメーターにします。

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

これは、stdlibが行う方法でもあります(のような述語を持つ事実上すべてのアルゴリズムを参照してくださいstd::sort)。このようにして、実行する(あなたの場合は不要な)型消去も回避しますstd::function

于 2012-10-23T08:47:05.313 に答える
5

std :: sort:を見てください。

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

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

このようにして、呼び出し可能なものを使用できます。

于 2012-10-23T08:32:50.273 に答える
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()です。このようにして、関数の代わりにオブジェクトを渡します。これにより、管理が容易になります。

于 2012-10-23T08:26:22.943 に答える
1

これを完全に修正する方法はわかりませんが、コンパイラが引数を推測できないことは明らかです。それらを明示的に示すことは、回避策として機能する可能性があります。

mergeSort< std::list<int>::iterator, bool >(container.begin(), container.end(), compare);

別の方法は、渡す関数を明示的に変換することですstd::function

比較関数の代わりに最後の引数を作成することでこれを実装することもできます。これoperator<は、より直感的だと思います。

于 2012-10-23T08:38:28.713 に答える
-1

mergeSort期待const TIteratorし、あなたのものはそうではありません。

于 2012-10-23T08:24:21.773 に答える