Meaning of code involving function binding - c++

Can someone explain what is going on in the below code snippet line by line
auto enq_func = [](std::queue<reg_t>* q, uint64_t x) { q->push(x); };
std::queue<reg_t> fromhost_queue;
std::function<void(reg_t)> fromhost_callback =
std::bind(enq_func, &fromhost_queue, std::placeholders::_1);
I think I get the gist of it, that fromhost_queue is a std::queue of each element of type reg_t which was typedef in the beginning of the code as uint64_t and its enqueue functionality is defined using the above three lines something like that.
I have trouble understanding line 1 as I haven't come across this type of function declaration like =[](...){...}; is this some sort of shorthand or something
Also, in the bind() part in line 3, the first argument is a function(here named as enq_func) that bind will be applied on the second argument mostly used to pass a reference of a queue the enq_func will be applied but the last is an argument which will we enqueued but I don't see the enq_func having any arguement
can someone clarify this?

This is a slightly overly-complex way to create a function-like callable object that pushes its argument into fromhost_queue. That is, fromhost_callback(123) will end up calling fromhost_queue.push(123).
auto enq_func = [](std::queue<reg_t>* q, uint64_t x) { q->push(x); };
This is a lambda expression that creates a callable object that pushes its second parameter into the queue pointed to by the first parameter. That is, enq_func(&fromhost_queue, 123) will call fromhost_queue.push(123).
std::function<void(reg_t)> fromhost_callback =
std::bind(enq_func, &fromhost_queue, std::placeholders::_1);
This creates a new callable object that wraps enq_func and automatically supplies its first argument, then stores that in a type-erased std::function container. So fromhost_callback(123) will automatically call enq_func(&fromhost_queue, 123).
There's no reason to do this in two steps though, a single lambda will do fine.
Assuming there's a good reason to use std::function then this will do the same thing:
std::queue<reg_t> fromhost_queue;
std::function<void(reg_t)> fromhost_callback =
[&fromhost_queue](uint64_t x) { fromhost_queue.push(x); }

Related

why and how to use bind() as predicate in 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.

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?

does auto deduce that a type is a pointer?

I am unclear about the usage of auto in a function I am looking over. Given a parameter defined like:
someFunction(const unique_ptr<BSTNode<int>>& node, paramType param) {
the body of the function establishes a local variable like this:
auto *localNode = node.get();
My understanding of auto is that it deduces the type of what is assigned to it at compile time. The docs state that unique_ptr::get() returns a pointer to the object that it manages. Given that fact, why is it necessary to add * to the variable declaration?
Using a * to deduce a pointer is unnecessary, but may be desirable. If the code is later changed such that the initializer no longer returns a pointer, the * will cause auto deduction to fail. If the code that uses this variable is designed with a pointer in mind, this may be a good thing.
why is it necessary to add * to the variable declaration?
It's not. The benefit is that it makes it exceedingly obvious to the reader that localNode is a pointer.

Pass rvalue by reference

I am struggling to turn this piece of code into a one-liner:
std::string filename = "cats";
std::shared_ptr<bmd2::Bmd2Dataset> ptr (new bmd2::Bmd2Dataset(filename, bmd2::File::FM_WRITE));
bmd2::bmd2Session::getInstance().addDataset(ptr);
The above works great -- but can I call addDataset without creating the lvalues (lines 1 + 2)?
Here is the declaration of addDataset():
int addDataset(std::shared_ptr<bmd2::Bmd2Dataset> &) throw (bmd2Exception);
bmd2::bmd2Session::getInstance().addDataset(
std::make_shared<bmd2::Bmd2Dataset>("cats", bmd2::File::FM_WRITE)
);
One statementer. :)
Interesting. For learning purposes, can you tell me if you can accomplish this without the make_shared() function call?
You can, using C++11's brace initialization syntax. Assuming addDataset isn't a template and has std::shared_ptr<bmd2::Bmd2Dataset> as its parameter,
bmd2::bmd2Session::getInstance().addDataset(
{ new bmd2::Bmd2Dataset("cats", bmd2::File::FM_WRITE) }
);
UPDATE: Oops. So addDataset() actually accepts an l-value reference why didn't you say so immediately?. addDataset()'s parameter can't bind to r-value parameters, which in the two above examples are. To solve this, you can either:
Make addDataset()'s parameter a const reference
int addDataset(const std::shared_ptr<bmd2::Bmd2Dataset> &) throw (bmd2Exception);
// ^^^^^
Do this if you don't need to modify the passed shared_ptr argument (i.e. modifying it so it points to another object).
Use your older method, though passing directly "cat" into the the new expression. UPDATE: Use std::make_shared!
auto ptr = std::make_shared<bmd2::Bmd2Dataset>("cats", bmd2::File::FM_WRITE);
bmd2::bmd2Session::getInstance().addDataset(ptr);
// ptr might now point to some other object
Do this if you want the passed argument's (ptr) value to be changed (i.e. after the call it might now point to a new object).

Convert lambda with capture clause stored in std::function to raw function pointer

Since my last recent question was unfortunately worded and resulted in a solution to another problem then mine, here I will try to formulate my actual problem in a clear way.
Before we start, as a sidenote, I am integrating the Javascript Engine V8 into my C++ application. That's where all the types in the example come from. And that's also the reason for the fact that I need a raw function pointer in the end. But I elaborate on this below.
From inside a class I need to pass a lambda expression with the capture clause [=] as parameter of the type std::function to another function and cast it to a raw function pointer there.
In this code, InvocationCallback is simply a typedef for a function with the signature Handle<Value>(Arguments const &).
typedef Handle<Value> (*InvocationCallback)(Arguments const &);
void Bind(string Name, function<Handle<Value>(Arguments const &)> Function)
{
InvocationCallback* function = Function.target<InvocationCallback>();
}
All the lambda expressions have the same signature, too. Note that Handle<String> is compatible to Handle<Value> in this example. It's given by the Javascript Engine V8, too.
Bind("name", [=](const Arguments& args) -> Handle<Value>{
Handle<String> result = String::New(Name().c_str());
return result;
});
C++ allows me to pass this lambda as std::function to the function above. But I guess a lambda expression also stores a reference to object it refers. Somehow the access specified by [=] must be realized. That might be the reasons that casting the std::function to a raw function pointer fails.
InvocationCallback* function = Function.target<InvocationCallback>();
There is neither a compile time error nor a runtime error but the debugger tells me that it results in a null pointer. But I need the raw function pointer for further processing. I guess I could convert the lambda after std::binding the reference or this-pointer first.
Update: Since it seems to be impossible to get the state out of the lambda, this is what I tried. It compiles but function come out to be a null pointer.
Bind("name", this, [](Base* object, const Arguments& args) -> Handle<Value>{
return v8::String::New(((Derived*)object)->Name().c_str());
});
void Bind(string Name, Module *Object, function<Handle<Value>(Module*, Arguments const &)> Function)
{
function<Handle<Value>(Arguments const &)> method = std::bind(Function, Object, std::placeholders::_1);
InvocationCallback* function = method.target<InvocationCallback>();
}
You can't, because a lambda which captures is a closure, so it has state (it is an object with instance variables). A function pointer has no state. Thus, you cannot do this without either 1) the API you are using that requires the function pointer also allows you to pass a user data argument where you pass the state, or 2) storing the state in a global variable or something.
Search around Stack Overflow for "member function to callback" and you will get an idea (basically, you are wanting to use a member function, the operator(), as a callback).
You can convert a capturing lambda/functor into a function pointer, but you need to be careful when doing it:
https://codereview.stackexchange.com/questions/79612/c-ifying-a-capturing-lambda