why and how to use bind() as predicate in c++? - c++

I'm given this strange-looking std::generate() function which create a std::vector of random number between a and b.
int myrand(int a, int b)
{
int div = b-a;
return a + (rand() % (b-a));
}
int main()
{
vector<int> v(20);
generate( v.begin(), v.end(), bind(myrand,1, 11) ); //fill with random no. bwt 1 and 10
return 0;
}
I know how std::generate() function works, one has to pass a predicate into the third argument. Predicate can be in the form of:
function
function object
function pointer.
But i'm quite confused by the expression bind(myrand,1, 11), why do we have to write it this way?
I know that bind returns a function which can be placed as the third argument here.
But, isn't myrand a function as well? I've tried to replace the third argument with myrand(1,11) and it won't work, why is it so?

std::bind takes a function object, and the thing(s) you want to pass the to function object, and returns a function object that will called the supplied function object with those parameter(s). That means
auto foo = bind(myrand,1, 11);
foo();
is the same as
myrand(1, 11);
To make life easier though, you can avoid bind and just use a lambda. Doing that would give you
generate( v.begin(), v.end(), [](){ return myrand(1, 11); });
And, at least for me, this is a lot clearer that you are getting a object that will return myrand(1, 11) every time you call it's operator().

std::bind doesn't return a function, it returns an object with a function-call operator operator() implemented. The object is a functor object that can be called like a function.
When you use myrand(1, 11) you call the function myrand and pass the int result to std::generate. This int value can't be "called" like a function.

why ... use bind()
It is generally recommended to use a lambda instead of std::bind.
std::bind is used to bind arguments to functions.
Using std::bind results in a function object with a function call operator that has a smaller arity than the original function.
How to use bind()
There is an example of how to use bind() in your question.
one has to pass a predicate into the third argument
Actually, the third argument is a generator.
But, isn't myrand a function as well?
Yes.
I've tried to replace the third argument with myrand(1,11) and it won't work, why is it so?
myrand(1,11) is not a function (nor a function object). It is a function call. The result is an int. int is not a function. You are trying to pass an integer as a callable, which does not work.

Bind returns a callable. When you bind both parameters of myrand, then the resulting callbale will take no parameters. It can be called like
std::bind(myrand,1,11)();
When you try to pass myrand(1,11) that is not a callable but an int.

But i'm quite confused by the expression bind(myrand,1, 11), why we
have to write it this way?
I know that bind returns a function which can be placed as the third
argument here.
But, isn't myrand a function as well? I've tried to replace the third
argument with myrand(1,11) and it won't work, why is it so?
myrand is a function. myrand(1,11) is an int.
bind takes a function, and some arguments, and returns a function-like object.
generate wants a function-like thing, not an int.

Related

Why isn't it possible to assign the result of std::bind to a function pointer

The result of an std::bind can be assigned to an std::function
A function pointer can be assigned to an std::function.
So far I was under the impression std::function can generally hold any function pointer. And anything an std::function can hold can be assigned to a function pointer.
And found that the reult of an std::bind can't be assigned to a function pointer
int add(int x, int y)
{
return x+y;
}
int main()
{
std::function<int (int, int)> fp = &add; // a func pointor can be assined to an std::function
int result = fp(3,5) // this works fine
std::function<int (int, int)> add_v2 = std::bind(&add, _1,_2); // std:: bind can be assigned to an std::function
int result = add_v2(3,5); // works fine
int (*add_v3)(int, int);
add_v3 = std::bind(&add, _1,_2); // does not compile
}
Can you please explain why I can't assign the result of std::bind to a function pointr
std::function knows how to invoke calls to multiple callable types, including plain functions, lambdas, and the result of std::bind(). Just because std::function can handle multiple callable types does not means the individual types are interchangeable/assignable with each other.
The return value of std::bind() returns a callable object of an unspecified type determined by the implementation. That type has an operator() that std::function calls. The bound object carries state information about the target object and class method it needs to call inside its operator(). So, by definition, such an object could never be assignable to a plain function pointer. There would be nowhere to store the state data, or even the bound object's own this pointer. The same reasons why a capturing lambda cannot be assigned to a plain function pointer, either.
add_v3 = std::bind(&add, _1,_2); // does not compile
As just the most obvious reason this can't be made to work, consider that all that's left after this line of code executes is a naked pointer. What can it point to?
The resulting bound function (the result of binding add to _1 and _2) clearly didn't exist before this line of code executes. And whatever std::bind created, it's a temporary that will no longer exist after this line executes.
So what could add_v3, a simple raw pointer, possibly point to? What would own it? What would manage its lifetime? When would it be destroyed?

non returning lambda with captures as function pointer

My code (C++) need to pass lambda as function pointer. My lambdas always: a) return void; b) never takes any parameter; and c) can have zero or more capture arguments. I want to pass this lambda as a function pointer but unable to do so. Any advice ?
Sample code:
void fptrfunc(void (*fptr)()){
fptr();
}
int main(){
int x = 2;
fptrfunc([](){cout << "LAMBDA CALL--1"<< endl; }); // Works
fptrfunc([x](){cout << "LAMBDA CALL--2"<< endl; }); // Does not compile
return 0;
}
Lambda functions which are really just functions, i.e., don't carry and data, can be converted to function pointers. To not have any data clearly the capture has to be empty. The other parts of the signature do't matter: as long as the types match, you can assign a lambda function [with an empty capture] to a function pointer.
The moment you need to have data with your lambda function you won't be able to convert it to a function pointer because there is no place to store the additional data. If you have a sensible interface where you need to pass the lambda function you may have some user data being passed along, often a void*. You could a combination of an auxiliary function pointer and a lambda, probably wrapped by a suitable std::function<Sig>, pointed to by the user data to still call a lambda function.
What you want, is not possible in C++. Lambdas that capture variables are not convertible to a function pointer.
You need to do drop the requirement c) and only use lambdas without captures. Or you must change the declaration of fptrfunc. You can change the parameter type to std::function or make it a template that can accept any type of functor that implements the operator().

Qt - Is this pass by reference?

If we write the following in Qtas an argument to a function: QString &tableName
Does that mean we are passing by reference?
Thanks.
Strictly speaking, that is a function parameter, not a function argument. The parameter is the variable declared inside the function's parameter list; the argument is the value passed to the function by the calling function. So parameter QString &tableName is passed by reference. But as a function argument, &tableName would mean "the address of tableName".
Updated: As requested, here is a code sample to clarify the distinction:
void f (double y) ;
f (99.0) ;
double y is a parameter declaration; it resembles a variable declaration. y is a function parameter.
99.0 is a function argument; it is an expression, that must be convertible to type double.
Yes, this is pass-by-reference in C++. You could also write QString const & tableName, if you don't want to have the very possibility of accidentally changing tableName.
Yes. Tip: make it const if you don't want it to change.
Note that, like most non-trivial Qt basic types, QString is a lightweight container object that implements "copy on write" semantics. So the only reason to pass one by reference is if your function wants to modify the caller's copy, and there is never any reason to pass one by const reference (unless you do not know much about Qt).

How can I define a function pointer that takes the same arguments and return value as a given function?

For example, I have a function foo:
int foo(int a, int b)
{
return a + b;
}
I can define a function pointer:
int (*pfoo)(int, int);
But how can I do this dynamically in program?
I want a function that takes a function as a parameter, and return a function pointer that takes the same arguments and return value as a given function.
Then I can use it like this:
void* pfoo = getFuncPtrFromFunc(foo);
Which does what the code above did.
Is this possible?
You cannot do this at run-time (i.e. dynamically); remember that all types (and function pointers are types) are statically determined at compile-time.
Imagine if you could do this, and you somehow obtained a function-pointer whose type was variable (i.e. it could point to a float (*)(int,int) or a char (*)(float)). How would you ever be able to call that and provide a meaningful list of arguments?
You can, however, get this information at compile-time; one way is to use the Boost TypeTraits library.
c++ is a static typed language, and doesn't allow to do what you want.

why did it compile errorly when i added a reference argument to a member function which is the argument to std::mem_fun()?

Firstly, I had a snippet as following:
struct D
{
int sum;
D():sum(0){accum();}
void incre(int arg){sum+=arg;}
void accum()
{
int arr[]={1,2,3,4,5};
std::for_each(arr,arr+ sizeof(arr)/sizeof(int),
std::bind1st(std::mem_fun(&D::incre),this));
cout << sum <<endl;
}
};
int main()
{
D();
}
It compiled properly.But after my changing the member function incre to
void incre(int & arg){sum+=arg;}
it produced errors, like
typename _Operation::result_type std::binder1st<_Operation>::operator()
(typename _Operation::second_argument_type&) const [with _Operation =
std::mem_fun1_t<void, D, int&>]’ cannot be overloaded
Do you have any ideas about what is going on? I'll appreciate any help.
What is going on is that bind1st and mem_fun do not work with references on all platforms.
You can use it with boost::bind
std::for_each( arr, arr + sizeof(arr)/sizeof(int),
boost::bind( &D::incre, this, _1 ) );
and it would seem GNU have decided the above is a good enough workaround to mark the bug as "won't fix".
In your case you could pass in by value. You can also happily pass pointers into these functions.
What you are doing should work, by the way.
Passing by value might not fix it either because you are calling a non-const member function. There was an issue also about non-const member functions.
Your other alternative of course is to use std::accumulate rather than std::for_each, which is suitable for this particular case where you are running through your collection generating something. The way I generally prefer to use accumulate is:
Result r;
Result* binaryfunc( Result*, T value ); // returns the same pointer passed in
std::accumulate( coll.begin(), coll.end(), binaryfunc, &r );
which avoids copying the "Result" on every iteration. There is no need to use bind1st or mem_fun here so no issue either if you are passing in value by reference.
The problem is that internally, mem_fun tries to set as its argument type a const reference to the argument type of the member function. If you make then function take in a reference, then it tries to create a reference to a reference, which is illegal in C++. This is a known defect in the library and is being remedied by the new bind function that will appear in C++0x.