2013-12-12 8 views
9

私は自分自身にいくつかの入力を保存し、したがって、このような何かを定義したいのですが?C++ 11結合ソート機能

ブーストの使用はオプションではありません。

最小限の作業例:

#include <vector> 
#include <utility> 
#include <algorithm> 
#include <functional> 

using namespace std; 

int main() { 

    vector<pair<int, int>> vec; 
    for (int i = 0; i < 10; i++) 
     vec.push_back(make_pair(10 - i, 0)); 

    auto vecsort = bind(sort, vec.begin(), vec.end(), [] (pair<int, int> const &a, pair<int, int> const &b) { 
      return a.first < b.first; 
     }); 

    vecsort(); 

} 

エラー:

error: no matching function for call to 'bind(<unresolved overloaded function type>, std::vector<std::pair<int, int> >::iterator, std::vector<std::pair<int, int> >::iterator, main()::__lambda0)'

+3

エラーメッセージはありますか? –

+0

@ R.MartinhoFernandesはい、いつものようにC++では非常にわかりにくいです。私は最小限の作業例を含んでいました。 – ryyst

+0

@ryyst:エラーメッセージを教えてください。最低限必要な作業例が含まれていないため、動作しません。 –

答えて

11

問題はstd::sortは関数オブジェクトではないということです。これは関数テンプレートです。問題に対処する最も簡単な方法は、単純なラッパーオブジェクトを作成することです:

struct sorter { 
    template <typename RndIt, typename Cmp> 
    void operator()(RndIt begin, RndIt end, Cmp cmp) { 
     std::sort(begin, end, cmp); 
    } 
}; 

は今、あなたは使用することができます

std::bind(sorter(), vec.begin(), vec.end(), [](...){ ... }); 
+0

これらのオブジェクトだけがそのようなPITAを作成するのではない場合... – Xeo

+0

@Xeoあなたは何か組織に何かを提案するか、それについて何かを行うことができるもの... – Yakk

+0

@ Yakk:うん、そうかもしれない。(https://dl.dropboxusercontent.com/u/14327987/functional_cpp.html);) – Xeo

7

他の人はそれがコンパイルされない理由を述べたが、この代替ソリューションの作業を行いいますあなたのために?これは、bindの代わりに別のラムダを使用してstd :: functionを作成します。

#include <vector> 
#include <utility> 
#include <algorithm> 
#include <functional> 
#include <iostream> 

using namespace std; 

int main() { 

    vector<pair<int, int>> vec; 
    for (int i = 0; i < 10; i++) { 
     vec.push_back(make_pair(10 - i, 0)); 
    } 

    auto vecsort = [&vec] { 
     sort(vec.begin(), vec.end(), 
     [] (pair<int, int> const &a, pair<int, int> const &b) { 
      return a.first < b.first; 
     }); 
    }; 

    // vecsort will work as long as vec is in scope. 
    // vecsort will modify the original vector. 
    vecsort(); 
    for (auto i : vec) { 
     std::cout << '(' << i.first << ", " << i.second << ") "; 
    } 
    std::cout << endl; 

    vec.push_back(make_pair(-42, 0)); 
    vecsort(); 
    for (auto i : vec) { 
     std::cout << '(' << i.first << ", " << i.second << ") "; 
    } 
    std::cout << endl; 
} 

出力:

(1, 0) (2, 0) (3, 0) (4, 0) (5, 0) (6, 0) (7, 0) (8, 0) (9, 0) (10, 0) 
(-42, 0) (1, 0) (2, 0) (3, 0) (4, 0) (5, 0) (6, 0) (7, 0) (8, 0) (9, 0) (10, 0) 

それはここで実行を参照してください:ここで http://ideone.com/W2YQKW

+0

はい、これは私のために働くと私はそれが好きです。ありがとう! – ryyst

3

は、この問題のために有用なマクロです。それがするのは、特定のコンテキストで特定の関数名(文字列値)を呼び出すオーバーロードの集合を表すインスタンスを持つ匿名のstructを作成することです。

C++にはこのような機能性が悲しみに欠けています。もし誰かがそれをC++標準化委員会に提案すれば。ああ。グローバルスコープで

#define OVERLOAD_SET(FUNCTION_NAME) struct { template<typename... Args>\ 
    auto operator()(Args&&... args) const->\ 
    decltype(FUNCTION_NAME(std::forward<Args>(args)...))\ 
    { return (FUNCTION_NAME(std::forward<Args>(args)...)); } \ 
} 

OVERLOAD_SET(std::sort) sorter; 

そして、使用の時点で:

std::bind(sorter, vec.begin(), vec.end(), [](...) {...}); 

問題はstd::sorttemplatetemplate(あるいはセットであることです実際の関数ではなく、呼び出されたときに関数を生成するオーバーロードによって選択されます)。それは関数のように見えますが、そうではありません。 templateとオーバーロードセットは他の関数に直接渡すことはできません。余談として

は、上記マクロOVERLOAD_SETの改良は、特定関数ポインタに暗黙的にキャストするOVERLOAD_SET可能template<typename R, typename... Args> operator R(*)(Args...)() constを添加することによって作製することができるが、これはこの問題の範囲を超えています。


XEOは、このような提案を行っています。

+0

C++はローカルクラスのメンバ関数テンプレートを禁止しているので、グローバルスコープで行う必要があります。また、式の一部として型を作成することはできないので、 'OVERLOAD_SET'関数を使って作成をインライン化するだけではできません。 – Xeo

+0

@Xeoポイント。テストされていないコンポーネントを削除しました。 – Yakk

関連する問題