How to std::bind a class function properly? - c++

class A
{
public:
A();
void Func1(int,int);
void Func2(long,long);
private:
...
};
<implementation here>
In main:
std::vector<std::function<void(void)>> fl;
A a;
fl.push_back(std::bind(&a.Func1, 1,1));
Gives the error:
ISO C++ forbids taking the address of a bound member function to form a pointer to member function
Solution?
Edit: changed "A a();" to "A a;". No constructor here :P
Edit:
Selected Praetorian's reply as answer because it solves the problem.
Dietmar Kühl's is a good solution too but not the actual answer to the question.
Gotta be fair :D

Func1 is a non-static member function, so it must be invoked on an instance of A, which you'll need to bind as the first argument (the this pointer). Also, when creating a pointer to member function, the syntax is &ClassName::MemFuncName.
So you need
fl.push_back(std::bind(&A::Func1, &a, 1, 1));
Make sure that the lifetime of a does not end before you invoke the bound function.

Two issues. First,
A a();
is a function declaration. You need
A a;
Then,
fl.push_back(std::bind(&A::Func1, &a, 1,1));

You could also just not use std::bind():
std::vector<std::function<void(void)>> fl;
A a{};
fl.push_back([&](){ a.Func1(1, 1); });
The code show references a on the stack. That's OK when the function object doesn't outlive a. If that can't be guaranteed you may want to replace the & by = which would copy the object. BTW, the subtle change from () to {} causes the code to declare a an object of type A rather than as a function taking no argument and returning A.

unfortunately C++ doesn't have a syntax like that. A complete example with the correct syntax would look like this:
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
class A
{
public:
A() {}
void Func1(int,int) {}
void Func2(long,long) {}
};
int main()
{
std::vector<std::function<void(void)>> fl;
A a;
fl.push_back(std::bind(&A::Func1, &a, 1,1));
return 0;
}
You need to provide two things (at least): 1) the pointer to member function 2) the implicit "this" pointer, i.e., the object you want to call the method on.
Then you can add the parameters you want to bind.
Note also that unfortunately you can't make an instance of "A" with "A a();" This is the "most vexing parse". The correct way is "A a;" or "A a{};"

Related

Function pointers on a class's member function

void Parser::add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand)
{
command_no_arg.push_back(comand);
func_no_arg.push_back(f);
}
void Parser::prepare()
{
//add_func_no_arg(Virtual_Machine::dump,"dump"); it work when i put it in static but i cant do that
add_func_no_arg(vm.clear,"clear"); // ERROR HERE the vm.clear does not fit
}
I have those two functions to try help my create a array of pointers func_no_arg;
I can't put the vm's func in static;
Why cant i have a pointer on a function when it is "trap" whit in one objet ? maybe the type is wrong, here is some .hpp :
class Parser {
public:
/***/
void prepare();
void add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand);
private:
Virtual_Machine vm;
std::vector<std::string> command_no_arg;
std::vector<void (Virtual_Machine::*)()> func_no_arg;
/***/
};
class Virtual_Machine {
public:
/***/
void clear();
/***/
}
and the compiler said this :
Parser.cpp: In member function ‘void Parser::prepare()’:
Parser.cpp:65:36: error: invalid use of non-static member function ‘void Virtual_Machine::clear()’
add_func_no_arg(vm.clear,"dump");
^
In file included from ../include/Parser.hpp:13,
from Parser.cpp:8:
../include/VM.hpp:23:14: note: declared here
void clear();
The syntax for getting a pointer-to-member is &Virtual_Machine::clear (not vm.clear), and a variable f of this type can be invoked on an instance of Virtual_Machine with the .* operator (e.g. vm.*f()).
Alternatively you could write &decltype(vm)::clear, which doesn't depend on the class name.
As written by IlCapitano you have to use a specific syntax to deal with pointer-to-members. Here is an example (compiled with g++ tmp.cpp -o tmp):
#include <iostream>
#include <string>
#include <vector>
class Virtual_Machine
{
private:
std::string name;
public:
Virtual_Machine(std::string n) : name(n) {}
void clear() { std::cout << "Clear " << name << std::endl; }
};
class Parser
{
private:
Virtual_Machine vm;
std::vector<std::string> command_no_arg;
std::vector<void (Virtual_Machine::*)()> func_no_arg;
public:
Parser(std::string vm_name) : vm(vm_name) {}
void add_func_no_arg(void (Virtual_Machine::* f)(), std::string command)
{
command_no_arg.push_back(command);
func_no_arg.push_back(f);
}
void prepare()
{
add_func_no_arg(&Virtual_Machine::clear, "clear");
}
void test()
{
(vm.*(func_no_arg[0]))();
}
};
int main()
{
Parser a("vm_a"), b("vm_b");
a.prepare();
b.prepare();
a.test();
b.test();
return 0;
}
The output of the program is:
Clear vm_a
Clear vm_b
A pointer to the member function clear of an instance of class Virtual_Machine is created with &Virtual_Machine::clear. To later call this function you have to use the operators .* or ->* with an instance of the class on the left side of the operator and the pointer to the function on the right side, like (vm.*(func_no_arg[0]))(). If the function would have parameters, you would place them in the most right pair of parentheses.
As mentioned above, the proper syntax to get a pointer to a member functions is &Class::member. The general idea behind this, is that when you declare a class, every function and types in that class belongs in a namespace named after your class. Thus the syntax for getting a pointer to member function is actually equivalent to any pointer to a function inside a namespace. Do keep in mind that access specifier still apply when trying to retrieve a pointer to a function in a class.
However, there is one big difference, in that when you declare a member function, an implicit parameter is added (this in c++), which you actually noted, which is why the type is return_type (Class::*) (parameters)
There are two way to handle this matter. The first one, as noted by others here is to use the instance when you need to call the function, by using the .* or ->* syntax (the dot or arrow are there to access the instance "internals", and the star to de-reference the function pointer).
Another way of doing this (mostly if you don't care about the object, or can't access it when you call it) is to wrap your function in an std::function, by "binding" the implicit this, and any parameter you need to, using std::bind.
By using std::function and std::bind together, you would be able to use the c-style syntax you're used to.
The example section for std::function and std::bind on cppreference show how to achieve this

What is the difference between "this" and "::"?

Inside setMyInt function I have used two statements to set myInt variable. Though both of them gives me the same result. Is there any conceptual difference in working of them?
#include <iostream>
using namespace std;
class Bar{
int myInt;
public:
const int getMyInt() const {
return myInt;
}
void setMyInt(int myInt) {
Bar::myInt = myInt;
this->myInt=myInt;
}
};
int main(){
Bar obj;
obj.setMyInt(5);
cout<<obj.getMyInt();
return 0;
}
You can't really compare them, and they are not interchangeable, but because in C++ you can leave certain things out in certain cases, here it looks like they are.
In fact, both lines are short for:
this->Bar::myInt = myInt;
This means, set the value of the object Bar::myInt (the member called myInt in the scope of the class Bar), which is encapsulated by the object pointed to by this, to the value of the (other) variable myInt.
You can leave out Bar:: because this is a Bar* so that's implicit; you can leave out this-> because you're in a member function so that's implicit too.
More generally, -> performs a pointer dereference and object access, whereas :: is the "scope resolution operator" which fully qualifies a name.
“->” is used as a pointer
“.” Is used for object members variables/ methods
“::” Is used for static variables/ methods or for objects from another scope.

How should I access a function of a container class in a contained class object

I have the following class structure
class containingClass
{
int func1(int a);
containedClass containedClassObject;
}
I want to access func1 in containedClass objects. What will be the best way to achieve that?
A naive solution that comes to mind is to pass a function pointer to the containedClass's constructor, but then I get into a circular definition, as I need to pass a pointer to an object of the containingClass as well.
Any suggestions?
The containedClass required a contract/API/function to be fulfilled by the int func1(int) member of the containingClass. Unless the containedClass explicitly requires access to an instance of the containingClass for other purposes, the access can be provided via lambda (or std::bind) and the containedClass can have a std::function with the correct signature member that holds the lambda.
The only "trick" here would be to ensure that the lifetime of the objects are managed appropriately, i.e. the lifetime of the containingClass instance is at least as long as required for use in the containedClassObject object.
A sample;
#include <functional>
class containedClass {
std::function<int(int)> functor_;
public:
void setter(std::function<int(int)> functor) { functor_ = functor; }
};
class containingClass
{
int func1(int a);
containedClass containedClassObject;
public:
containingClass()
{
containedClassObject.setter([this](int a) -> int { return this->func1(a); });
}
};
Even if this already over a year old, I would like to help other seraching people.
Here is another example using a reference to the containing class. Tested with mingw32-g++ 4.9.2 and -std=c++98. Means it should work also with c++0x and c++11
#include <string>
#include <iostream>
using namespace std;
class clsDog;
class clsEar{
public:
clsDog& myDog;
clsEar(clsDog &dog);
};
class clsDog{
public:
clsEar ear;
void pain(string fromPart){
cout << "dog has pain in his " << fromPart << endl;
}
clsDog():ear(*this){};
};
clsEar::clsEar(clsDog &dog): myDog(dog){
myDog.pain("ear");
}
int main(){
clsDog dog;
}
First class clsDog makes it available for reference and pointers. NOT for actual values like non reference member variables.
In class clsEar a reference to clsDog is created using clsDog& myDog. The constructor can set the reference pointer in the initializer list. It is important that the containing class clsDog is passed by reference otherwise the compiler tell you that the class incomplete.
Because clsEar is now fully defined a normal member variable of clsEar can be defined in clsDog. Because clsEar's constructor needs a reference to clsDog it must be passed to it's constructor. This is done in the initialisier list of clsDog's constructor by passing *this.
Last but not least the implementation of clsEar::clsEar must be done. It is necessary to do this after the complete definition of clsDog to call the member functions or access member varibales of clsDog in clsEar. Otherwise the compiler will tell you again, that the class clsDog is of incomplete type.

C++: when we should use "this->" PLUS parameters by reference

suppose we have a class
class Foo {
private:
int PARTS;
public:
Foo( Graph & );
int howBig();
}
int Foo::howBig() { return this->PARTS; }
int Foo::howBig() { return PARTS;       }
Foo::Foo( Graph &G ) {
<Do something with G.*>
}
Which one of howBig()-variants is correct?
The &-sign ensures that only the reference for Graph object
is passed to initialization function?
In C I would simply do something like some_function( Graph *G ),
but in C++ we have both & and *-type variables, never understood
the difference...
Thank you.
When you've local variable inside a member function, then you must have to use this as:
Foo::MemberFunction(int a)
{
int b = a; //b is initialized with the parameter (which is a local variable)
int c = this->a; //c is initialized with member data a
this->a = a; //update the member data with the parameter
}
But when you don't have such cases, then this is implicit; you need to explicity write it, which means in your code, both versions of howBig is correct.
However, in member initialization list, the rules are different. For example:
struct A
{
int a;
A(int a) : a(a) {}
};
In this code, a(a) means, the member data a is being initialized with the parameter a. You don't have to write this->a(a). Just a(a) is enough. Understand this visually:
A(int a) : a ( a ) {}
// ^ ^
// | this is the parameter
// this is the member data
You can use this-> to resolve the dependent name issue without explicitly having to spell out the name of the base. If the name of the base is big this could arguably improve readability.
This issue only occurs when writing templates and using this-> is only appropriate if they're member functions, e.g.:
template <typename T>
struct bar {
void func();
};
template <typename T>
struct foo : public bar {
void derived()
{
func(); // error
this->func(); // fine
bar<T>::func(); // also fine, but potentially a lot more verbose
}
};
Which one of howBig()-variants is correct?
both in your case, the compiler will produce the same code
The &-sign ensures that only the reference for Graph object is passed to initialization function? In C I would simply do something like some_function( Graph *G ), but in C++ we have both & and *-type variables, never understood the difference...
there is no difference as per the use of the variable inside the method(except syntax) - in the case of reference(&) imagine as if you've been passed an invisible pointer that you can use without dereferencing
it(the &) might be "easier" for clients to use
Both forms of Foo::howBig() are correct. I tend to use the second in general, but there are situations that involve templates where the first is required.
The main difference between references and pointers is the lack of "null references". You can use reference arguments when you don't want to copy the whole object but you want to force the caller to pass one.
Both are correct. Usually shorter code is easier to read, so only use this-> if you need it to disambiguate (see the other answers) or if you would otherwise have trouble understanding where the symbol comes from.
References can't be rebound and can't be (easily) bound to NULL, so:
Prefer references to pointers where you can use them. Since they cannot be null and they cannot be deleted, you have fewer things to worry about when using code that uses references.
Use const references instead of values to pass objects that are large (more than say 16 or 20 bytes) or have complex copy constructors to save copy overhead while treating it as if it was pass by value.
Try to avoid return arguments altogether, whether by pointer or reference. Return complex object or std::pair or boost::tuple or std::tuple (C++11 or TR1 only) instead. It's more readable.

Misunderstanding function pointer - passing it as an argument

I want to pass a member function of class A to class B via a function pointer as argument. Please advise whether this road is leading somewhere and help me fill the pothole.
#include <iostream>
using namespace std;
class A{
public:
int dosomeA(int x){
cout<< "doing some A to "<<x <<endl;
return(0);
}
};
class B{
public:
B(int (*ptr)(int)){ptr(0);};
};
int main()
{
A a;
int (*APtr)(int)=&A::dosomeA;
B b(APtr);
return 0;
}
This brilliant piece of code leaves me with the compiler error:
cannot convert int (A::*)(int)' toint (*)(int)' in initialization
Firstly I want it to compile.
Secondly I don't want dosomeA to be STATIC.
Pointers to members are different from normal function pointers. As the compiler error indicates the type of &A::dosomeA is actually int (A::*)(int) and not int (*)(int).
Inside B's constructor you need an instance of A to call the member on using one the .* or ->* operators.
E.g'
B(int(A::*ptr)(int))
{
A atmp;
(atmp.*ptr)(int);
}
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
You don't have a pointer to a function that returns an int and takes an int. You have a pointer to a member-function that returns an int and takes an A* and an int. Not only do you need to fix the type of your pointer, B needs to provide an A* to serve as dosomeA's this parameter.
Boost::bind has some functionality meant to simplify using function pointers in general, and they provide support for pointers to member functions. See here.