std::bind on member with call operator - c++

This might be a silly and stupid thing to do - however I would like to understand what happens here.
I have the following code:
#include <iostream>
#include <functional>
namespace
{
struct call
{
void operator()() const
{
std::cout << "call::operator()" << std::endl;
}
};
struct dummy
{
dummy() = default;
dummy(const dummy&) = delete;
call member;
};
}
So member essentially would work like any other object method, allowing it to be invoked as:
dummy d;
d.member()
Which would print call::operator().
Now I would like to use bind to do that, the initial implementation looked like this:
int main()
{
dummy d;
auto b = std::bind(&dummy::member, &d);
b();
return 0;
}
This compiles, but nothing is printed. I don't really understand what is happening - the fact that it compiles, but produces no output puzzles me :) surely some magic is going on inside the belly of std::bind, but what?
Here is a link to play with the code:
https://ideone.com/P81PND

Currently, your bind return a member, so b() is d.member.
You would have to call operator () on that:
b()(); // call::operator()
As alternative, you may use any of:
b = std::bind(&call::operator(), &d.member);
b = [&]() {d.member();};

You can also call through a std::reference_wrapper. No need for bind at all.
int main()
{
dummy d;
auto b= std::cref(d.member); // create reference wrapper
b();
return 0;
}

Related

C++ std::bind Function as Parameter Store in Class Variable

I have the following problem. class A implements some routines that should be used on a dataset that is being processed in Class B. That means I'm calling the function start from class A. What I'm doing should be saved in a variable m in class A. So far so good. However, when accessing class variable m it is still on the state when initialized.
To be precise:
#include <iostream>
#include <functional>
class A {
public:
int m;
A() {
m = 100;
}
void start(int value) {
std::cout << "hello there!" << std::endl;
m = value;
}
};
class B {
private:
int m;
public:
void doSomething() {
A a;
doSomething2(std::bind(&A::start,a, std::placeholders::_1));
// access variable m of instance a
std::cout << a.m << std::endl;
}
template <typename Callable>
void doSomething2(Callable f) {
int val = 4444;
f(val);
}
};
main()
{
B b;
b.doSomething();
}
When executing this, I'll get 100 as an output for m. How will I be able to have the changes made by the call of start stored in the class variable? Meaning, storing the value 4444 as in this example? Thanks
Looks like you'll want to make sure that std::bind is using a pointer to the actual class instance you've created. Try changing it to:
// notice I've got '&a' here instead of just 'a'
doSomething2(std::bind(&A::start, &a, std::placeholders::_1));
Without this, I would guess what bind is doing now is making a copy of the a instance and then modifying that one instead of changing it in place.
Bind by default takes arguments by value, in result start() acts on a copy of object a. You have to pass it by reference:
doSomething2(std::bind(&A::start, std::ref(a), std::placeholders::_1));
Possible alternative is to use a lambda expression instead.

vector of call back functions and function pointer binding

I am new to the std::function and trying to implement a callback function. In the following code "Callback_t" contains a function that holds a vector of function to be called. Class "other" is a nested class inside "SomeClass". An object of "SomeClass" contains an array of nested class object "b". The "other" class constructor assigns a function pointer to "fptr". I push this function in to the vector of callback class "Callback_t". When I run this code, I get the segmentation fault when the first function in the vector is invoked. I am not able to figure out what is wrong with the statement
this->loc_ptr->set_of_cb.push_back(this->b[i].fptr);
However if I replace it with
this->loc_ptr->set_of_cb.push_back(std::bind(&other::func, &(this->b[i])))
the code works perfectly. I need help to understand what's wrong with the original statement.
#include <functional>
#include <iostream>
#include <vector>
typedef std::function<void(void)> func_type;
class Callback_t {
public:
std::vector<func_type> set_of_cb;
void myCallback()
{
for (int i = 0; i < set_of_cb.size(); i ++){
set_of_cb[i]();
}
}
};
class SomeClass;
class SomeClass {
private:
Callback_t *loc_ptr;
int a[10];
class other{
public:
int id;
SomeClass *loc;
func_type fptr;
other(){};
other(SomeClass *loc, int id){
this->id = id;
this->loc =loc;
fptr = std::bind(&other::func,this);
}
void func(void){
this->loc->a[id] = loc->a[id] * id;
return;
}
};
public:
other *b;
//other b[10];
SomeClass(Callback_t *a = nullptr){
this->loc_ptr = a;
this->b = new other[10];
for(int i =0; i <10;i++){
this->a[i] = i;
this->b[i] = other(this, i);
this->loc_ptr->set_of_cb.push_back(this->b[i].fptr);
}
}
void read(void){
for(int i =0; i <10;i++){
std::cout<<a[i]<<std::endl;
}
}
};
int main()
{
Callback_t *tmp;
tmp = new Callback_t;
SomeClass tmp1(tmp);
tmp1.read();
tmp->myCallback();
tmp1.read();
delete tmp;
}
other(SomeClass *loc, int id){
this->id = id;
this->loc =loc;
fptr = std::bind(&other::func,this);
}
The constructor binds fptr to this, which is the constructed object. Now, pay careful attention:
this->b[i] = other(this, i);
This performs the following sequence of events. There are quite a few things happening here, that are crucial to this mystery:
A temporary other object gets constructed, and its constructor does what it does. Note that the object is temporary, so its constructor ends up binding its fptr to a temporary object! You're beginning to see the problem, but let's close the loop, anyway:
The object gets assigned to this->b[i]. This is effectively a copy.
The original temporary objects gets destroyed.
The end result is that b[i]'s bound function ends up getting bound to a temporary object that is now destroyed. This results in undefined behavior and your crash.
And with your working alternative:
this->loc_ptr->set_of_cb.push_back(std::bind(&other::func, &(this->b[i])))
You are binding the std::function to a valid instance of the object, in b[i].
That's it.
The other answer explains what is going wrong in your code. What is left to do is to show case a more canonical example of achieving what you go for (with a little help from lambda functions). Of course, std::bind() also works, but it is pre C++11 and I think nowadays most would rather do it as I do in my code below.
#include <iostream>
#include <functional>
#include <vector>
class Foo {
public:
void FooFun() {
std::cout << "Foo::FooFun() called" << std::endl;
}
};
class Bar {
public:
void BarFun() {
std::cout << "Bar::BarFun() called" << std::endl;
}
};
using CallbackFun_t = std::function<void()>;
using Callbacks_t = std::vector<CallbackFun_t>;
int main(int argc, const char * argv[]) {
Foo foo{};
Bar bar{};
Callbacks_t callbacks
{ [&foo]{ foo.FooFun();}
, [&bar]{ bar.BarFun();}
};
for( auto& cb : callbacks ) {
cb();
}
return 0;
}

Call a C-style function address with std::bind and std::function.target using a method from object

I have a C-style function, which stores another function as an argument. I also have an object, which stores a method that must be passed to the aforementioned function. I built an example, to simulate the desired situation:
#include <functional>
#include <iostream>
void foo(void(*f)(int)) {
f(2);
}
class TestClass {
public:
std::function<void(int)> f;
void foo(int i) {
std::cout << i << "\n";
}
};
int main() {
TestClass t;
t.f = std::bind(&TestClass::foo, &t, std::placeholders::_1);
foo( t.f.target<void(int)>() );
return 0;
}
What is expected is that it will be shown on screen "2". But I'm having trouble compiling the code, getting the following message on the compiler:
error: const_cast to 'void *(*)(int)', which is not a reference, pointer-to-object, or pointer-to-data-member
return const_cast<_Functor*>(__func);
As I understand the use of "target", it should return a pointer in the format void () (int), related to the desired function through std :: bind. Why didn't the compiler understand it that way, and if it is not possible to use "target" to apply what I want, what would be the alternatives? I don't necessarily need to use std :: function, but I do need the method to be non-static.
This is a dirty little hack but should work
void foo(void(*f)(int)) {
f(2);
}
class TestClass {
public:
void foo(int i) {
std::cout << i << "\n";
}
};
static TestClass* global_variable_hack = nullptr;
void hacky_function(int x) {
global_variable_hack->foo(x);
}
int main() {
TestClass t;
global_variable_hack = &t;
foo(hacky_function);
return 0;
}
//can also be done with a lambda without the global stuff
int main() {
static TestClass t;
auto func = [](int x) {
t->foo(x); //does not need to be captured as it is static
};
foo(func); //non-capturing lambas are implicitly convertible to free functions
}

Calling function from std::array of function pointers

I can't figure out how to call function pointer stored in std::array which is member of class.
namespace logic {
class Chance {
std::array<void(logic::Chance::*)(), 15> m_redChances;
};
}
void logic::Chance::redChance1 {
std::cout << "Red chance one\n";
}
logic::Chance::Chance()
{
m_redChances[0] = &Chance::redChance1;
}
It looks fine till now, but when I want to call this function in another member function, nothing seems to work. Only first line compiles, but it doesnt call my function. Rest are giving erros:
logic::Chance::anotherMemberFunction() {
m_redChances[0];
(*m_redChances[0]*)();
(*logic::Chance::m_redChances[0])();
m_redChances[0]();
*m_redChances[0]();
*logic::Chance::m_redChances[0]();
*logic::Chance::m_redChances[0];
*(*m_redChances[0])();
}
operand of "*"must be a pointer type
and
expression precending parentheses of apprent call must have
(pointer-to-) function type
EDIT#
So I tried to use std::function and had to change class design a bit, I want to achieve something like this
struct Foo {
std::array<std::function<void(Foo&)>, 3> funArray;
Foo() {
funArray[0] = &Foo::fun1;
funArray[1] = &Foo::fun2;
}
void fun1() {
std::cout << "fun1\n";
}
void fun2() {
std::cout << "fun2\n";
}
std::function<void(Foo&)> getFunction(int i) {
return funArray[i];
}
};
int main() {
Foo foo;
foo.getFunction(0);
std::cin.get();
}
As you can guess, this isn't calling my function and I again, tried every combination to return this correctly, but cant figure it out, thats the only one that compiles, but does nothing. How can I return a function call of function sotred in std::array by another function? A bit messy, but hope you get what I mean.
std::array<void(logic::Chance::*)(), 15> m_redChances is an array of pointers to a non-static member function of objects of class Chance. Therefore, you need to apply the object where the pointed-to member function is going to be called.
In the statement:
(*logic::Chance::m_redChances[0])();
no object is provided. On which object's data is that call going to be performed?
Considering chance an object of Chance and chance_ptr a pointer to an object of the same type, the call would be performed this way:
(chance.*m_redChances[0])();
(chance_ptr->*m_redChances[0])();
That is, by using the operators .* and ->*, respectively.
In your std::function example you can simply change
foo.getFunction(0);
to instead say
foo.getFunction(0)(foo);
This has to do with the same reason talked about in the other answers, a pointer to member-function is not in itself linked to an object. It needs a this to work on.
If you want to bind the std::function to a specific object you can use a
lambda to do that, like this.
#include <iostream>
#include <array>
#include <functional>
struct Foo {
std::array<std::function<void()>, 3> funArray; // Notice the change in signature to void()
Foo() {
funArray[0] = [&](){ fun1(); }; // Here & is catching this by reference and this lambda will always call fun1 on the current object.
funArray[1] = [&](){ fun2(); };
}
void fun1() {
std::cout << "fun1\n";
}
void fun2() {
std::cout << "fun2\n";
}
std::function<void()> getFunction(int i) {
return funArray[i];
}
};
int main() {
Foo foo;
foo.getFunction(0)(); // We get a function returned, so we need to call if by adding one more () at the end
auto storedFunction = foo.getFunction(1); // We can also store it
storedFunction(); // and call it later
}
A member function needs to be called on an object, to serve as the *this current object. You use the .* and ->* operators to call it with an object. E.g. (o.*mf)( args ).
Silly-fact noted by Andrei in his Modern C++ Programming book: o.*mf produces a callable entity that has no type.
In C++11 and later you can use std::function to effectively store such an object+function pointer pair, as a callable entity. Some other languages support it directly. E.g., it corresponds to a C# delegate.
Example.
#include <array>
#include <iostream>
using namespace std;
struct Foo
{
void blah() { cout << "Blah!" << endl; }
};
auto main()
-> int
{
array<void (Foo::*)(), 3> mf = {nullptr, nullptr, &Foo::blah};
Foo o;
Foo* o_ptr = &o;
(o_ptr->*mf[2])();
}

Passing a class method as function argument

I am trying to send a method of a specific class instance as an argument to a function (foo), although I keep getting this error
invalid use of non-static member function...
(from the line foo(a->bar))
I'm not sure why do I get this error? Is there a possible work-around for it?
#include <iostream>
#include <functional>
void foo(std::function<void(void)> _func)
{
_func();
}
class A
{
public:
A()
{
x = 5;
}
void bar()
{
std::cout << x << std::endl;
}
private:
int x;
};
int main() {
A a;
foo(a->bar);
return 0;
}
You have two options:
Use std::bind: foo(std::bind(&A::bar, a)):
Use lambdas: foo([&a]() { a.bar(); });
Your method isn't compatible to std::function, even it looks like.
Every method has an implicit first argument, this.
So your signature looks like this
void bar(A* this) { /* ... */ }
This is not the case for static methods. These are like functions within the namespace of the class and
static void bar() { /* ... */ }
Will saturate std::function.
Still, using a lambda (c++11) is most likely the better way for ur example.