2016-07-13 19 views
6

'daki işlevsel nesneler için nasıl çalışır? Aşağıdaki find_if işleviyle karşılaştım.bağlama işlevi, C++

find_if (coll.begin(), coll.end(), 
      bind(logical_and<bool>(), 
        bind(greater<int>(),_1,x), bind(less<int>(),_1,y) 
       ) 
     ); 

şüphe ne kadar bağlanır (yüksek(), _ 1, x) ve bağlama (daha az(), _ 1, y) değerlendirilir ve geri BOOL değerler vardır mi var? Bu, aşağıda gösterildiği gibi çalışmaz.

#include <iostream> 
#include <functional> 

int main() 
{ 
    using namespace std::placeholders; 

    //auto fn = std::bind(std::greater<int>(), 5, _1); 
    //std::cout << fn(7) << std::endl; 
    //std::cout << typeid(fn).name() << std::endl; 

    auto fn1 = std::bind(std::greater<int>(),5,6); 
    auto fn2 = std::bind(std::less<int>(),7,5); 

    std::cout << std::bind(std::logical_and<bool>(), fn1, fn2)(); // how this works?? 
    std::cout << std::logical_and<bool>()(fn1, fn2)(); // Compilation error 
} 

Bağlayıcıların bind işlevinin içinde nasıl çağrıldığını bilmek gerçekten meraklıdır. Birisi bunun nasıl çalıştığını açıklayabilir mi? Şimdiden teşekkürler.

+0

[ 'std düşünüldüğünde :: logical_and'] (http://en.cppreference.com/w/cpp/utility/functional/logical_and) * argümanlarını değerlendirir ve onları çağırmaz, gösterdiğiniz kod işe yaramaz. –

+3

'bind', yinelemeli olarak çağrıldığında çok ilginçtir. Lütfen sadece lambdas kullanmayı düşünün. – Yakk

+0

Hala tam olarak anlaşılmadı. Ama yorumunuzdan, bağlama fonksiyonunun dahili olarak functor'ları çağıracağını ve bunun sonucu logical_and'a bağlandığını anlıyorum. emin değil :( –

cevap

5

Bunu anlamak için , bind, bağımsız değişkenleri bağladığını anlamak için 1 st gerekir. depolanan bağımsız değişken arg tip std::reference_wrapper<T> (örneğin, std::ref veya std::cref bağlamak için ilk arama kullanılmıştır) arasında ise

  • : g(u1, u2, ... uM): g ile adlandırılan bir bind ifade sonucu olduğu göz önüne alındığında, Daha sonra, numaralı çağrıdaki vn argümanı arg.get() ve aynı çağrı Vn tipi T&: argüman argümanı çağrılan fonksiyon nesnesine referans olarak iletilir.
  • Depolanan değişken argümanı, std::is_bind_expression<T>::value == true için std::is_bind_expression<T>::value == true (anlamı başka bir bağlama ifadesi doğrudan bağlanacak ilk çağrıya iletildi) türündeyse, bağlama işlevi işlevi yerine getirme işlevi nesnesini iletmek yerine, işlev bileşimini gerçekleştirir: return, subexpression hevesle çağırılır ve dönüş değeri dışa çağrılabilir nesneye geçirilir. Bağlantı alt ifadesinin herhangi bir yer tutucu bağımsız değişkeni varsa, bunlar dış bağlama ile paylaşılır (u1, u2, ...). Özellikle, numaralı çağrıdaki vn argümanı arg(std::forward<Uj>(uj)...) ve aynı çağrı Vn türünde std::result_of_t<T cv &(Uj&&...)>&& (cv kalifikasyonu g ile aynıdır).
  • kayıtlı bağımsız değişken arg olan std::is_placeholder<T>::value != 0 anlamı, bir tutucu gibi std::placeholders::_1, _2, _3, ... bağlamak için ilk arama için bağımsız değişken olarak kullanılmıştır, tip T arasında ise), o zaman bağımsız değişken ile gösterilen invokable nesneye iletilen tutucu (_1 için u1, _2 için u2, vs.): std::invoke çağrısında bağımsız değişken vn yukarıda std::forward<Uj>(uj) ve aynı çağrı karşılık gelen tip VnUj&& olup.
  • Aksi takdirde, sıradan depolanmış bağımsız değişken arg lvalue değişken olarak Invokable nesneye iletilen: Yukarıdaki std::invoke çağrısında değişken vn sadece Arg ve karşılık gelen tip Vncv ile aynı ev yeterlilik olduğu, T cv & olduğu g.

anahtar 2 nd kurşunla içindedir.

std::cout << std::bind(std::logical_and<bool>(), fn1, fn2)() 

Ama bağlama ifadeleri tanımlı hiçbir & operatör olmadığı için, bu işe yaramaz: bağlama ifadeleri bağlama anda çağrılır olduğundan bu işleri

std::cout << std::logical_and<bool>()(fn1, fn2)() 
+0

Ayrıntılı açıklama için teşekkürler.Şu anda açık .. –

+2

@PaulVarghese Ben 'bind' için 'bind' için bunu açıkça ve bind_1st ve bind_2nd 'günlerinde arka ile olan aşinalık için seviyorum. , derleyiciler lambdaların optimizasyonu için 'bind' optimizasyonunu azalttılar.Bu en azından gcc için geçerli: https://youtu.be/ZlHi8txU4aQ Visual Studio'nun her şeye inandığı yerlerden emin değilim, ama genel iklim diyor lambdas 'bind's tercih ederim. –