2013-12-12 34 views
9

bağlayıcı kendime biraz yazmaktan kurtarır ve bu nedenle böyle bir şey tanımlamak istiyorum: - neden bu derleme değil NedenseC++ 11 - sıralama işlevini

using namespace std; 

vector<MyClass> vec; 

auto vecsort = bind(sort, vec.begin(), vec.end(), [] (MyClass const &a, MyClass const &b) { 
     // custom comparison function 
    }); 

vecsort(); // I want to use vecsort() a lot afterwards 

?

Yükseltme kullanmak bir seçenek değildir.

En az bir çalışma örneği:

#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(); 

} 

hatası:

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

Bir hata mesajı var mı? –

+0

@ R.MartinhoFernandes Evet, her zaman olduğu gibi C++ ile de çok şifreli. Yine de minimal bir çalışma örneği ekledim. – ryyst

+0

@ryyst: Bize hata mesajını bildirin. BTW minimal çalışma örneğiniz içermediği için çalışmaz. –

cevap

11

sorun std::sort bir işlev nesne olmadığıdır. Bu bir işlev şablonudur. konuyla ilgilenmesi için en kolay yolu basit bir kapsayıcı nesnesi oluşturmaktır:

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

bunu derleme değil neden Diğerleri belirtmiştik

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

Sadece bu nesneler oluşturmak için böyle bir PITA değildi ... – Xeo

+0

@Xeo Bazı organizasyonlar veya bu konuda bir şeyler yapabilecek bir şey bir şey teklif etmelisiniz ... – Yakk

+0

@Yakk: Evet, [belki de yapmalıyım.] (Https://dl.dropboxusercontent.com/u/14327987/functional_cpp.html);) – Xeo

7

kullanabilirsiniz, ancak bu alternatif çözüm çalışır senin için? Bu std :: işlevini oluşturmak için bağlama yerine başka bir lambda kullanır.

#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; 
} 

Çıktı:

(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) 

burada çalıştırmak bakınız: Burada http://ideone.com/W2YQKW

+0

Evet, bu benim için çalışıyor ve beğendim. Teşekkürler! – ryyst

3

bu soruna yönelik bir yardımcı makrosudur. Bu, belirli bir bağlamda belirli bir işlev adını (dize değerine) çağıran aşırı yükleme kümesini temsil eden anonim bir struct oluşturmaktır. C++ böyle bir işlevsellikten yoksundur. Eğer sadece bir kişi C++ standardizasyon komitesine teklif ederse. Ne yazık ki. Küresel kapsamında

#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; 

sonra kullanım noktasında:

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

sorun std::sorttemplate bir template (ya da muhtemelen bir dizi olmasıdır Gerçek bir işlev değil, çağrıldığında işlevler üreten aşırı yük ile seçildi! Bir işleve benziyor, ama öyle değil. Ve template s ve aşırı yük setleri doğrudan diğer işlevlere geçirilemez. Bir kenara

yukarıda makro OVERLOAD_SET bir gelişme, belirli bir fonksiyon işaretçisi dolaylı döküm için OVERLOAD_SET sağlayan bir template<typename R, typename... Args> operator R(*)(Args...)() const ekleyerek yapılabilir, ancak bu, bu sorunun kapsamı dışındadır.


Xeo

böyle bir öneri yaptı.

+0

C++, yerel sınıflar için üye işlev şablonlarını yasakladığından, bunun küresel kapsamda gerçekleşmesi gerektiğini unutmayın. Ve bir ifadenin parçası olarak türleri oluşturamadığınız için, yaratımı sadece OVERLOAD_SET işleviyle satır içi olarak yapamazsınız. – Xeo

+0

@Xeo noktası. Test edilmemiş bileşenler silindi. – Yakk