I came across the following find_if function.
find_if (coll.begin(), coll.end(), 
             bind(logical_and<bool>(), 
                  bind(greater<int>(),_1,x), bind(less<int>(),_1,y)
                 )
         );
I've the doubt that how the bind(greater(),_1,x) and bind(less(),_1,y) are evaluated and returning bool values there? This will not work otherwise as shown below.
#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
}
Really curious to know how the functors are called inside the bind function. Can someone please explain how this works? Thanks in advance.
To understand this we'll need to 1st understand how bind, binds it's arguments. Given that g is the result of a bind expression which is called with: g(u1, u2, ... uM):
- If the stored argument arg is of type
 std::reference_wrapper<T>(for example,std::reforstd::crefwas used in the initial call to bind), then the argumentvnin thestd::invokecall above isarg.get()and the typeVnin the same call isT&: the stored argument is passed by reference into the invoked function object.- If the stored argument arg is of type
 Tfor whichstd::is_bind_expression<T>::value == true(meaning, another bind expression was passed directly into the initial call to bind), then bind performs function composition: instead of passing the function object that the bind subexpression would return, the subexpression is invoked eagerly, and its return value is passed to the outer invokable object. If the bind subexpression has any placeholder arguments, they are shared with the outer bind (picked out ofu1,u2, ...). Specifically, the argumentvnin thestd::invokecall above isarg(std::forward<Uj>(uj)...)and the typeVnin the same call isstd::result_of_t<T cv &(Uj&&...)>&&(cv qualification is the same as that ofg).- If the stored argument arg is of type
 T, for whichstd::is_placeholder<T>::value != 0, meaning, a placeholder such asstd::placeholders::_1,_2,_3, ... was used as the argument to the initial call to bind), then the argument indicated by the placeholder (u1for_1,u2for_2, etc) is passed to the invokable object: the argumentvnin thestd::invokecall above isstd::forward<Uj>(uj)and the corresponding typeVnin the same call isUj&&.- Otherwise, the ordinary stored argument arg is passed to the invokable object as lvalue argument: the argument
 vnin thestd::invokecall above is simply arg and the corresponding typeVnisT cv &, wherecvis the same cv-qualification as that ofg.
The key is in the 2nd bullet. Because the bind expressions are invoked at binding time this works:
std::cout << std::bind(std::logical_and<bool>(), fn1, fn2)()
But because there is no & operator defined for bind expressions, this won't work:
std::cout << std::logical_and<bool>()(fn1, fn2)()
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With