Restricting functions that can be passed to another function in C++ - c++

I have a class containing several very similar functions and a couple other functions that take those interchangeably functions as input.
A simpler example:
class functions{
public:
int a();
int b();
int F(int (*f)() ); //f can only be a() or b()
};
Before I put them in a class, I had something like
if(f!=a || f!=b) cout<<"error";
With the class, it seems to just get more complicated, since I believe I now need to pass a class instance or something to get rid of my error: invalid use of member function
I have just started to learn about enumerated lists, and it seems like that would do the job if I was dealing with normal variables. Can I create an enum of functions?
What is the best way to restrict functions that can be passed to another function?
I'm pursuing the static cast method, but still needing help with int F( int(*f)() );
int functions::F(int (functions::*f)() )
{
if(f==functions::a)
//gives error: invalid operands of types 'int (functions::*)()'
// and 'int (int(*)()' to binary operator =='
int x=f();
//gives error: must use ‘.*’ or ‘->*’ to call pointer-to-member
//function in 'f(...)'
int y=(functions.*f)();
//gives error: expected primary-expression before ‘.*’ token
return 0;
}

It really depends on what you want to achieve:
I'd say largely that this sort of restriction is best validated by code review rather than coding...
The other solution is to not use that construct at all, and making a Fa() and Fb() function that calls the (private) a() and b() member functions.
And the remainder of the question is "how do I call a member function of a class" -the answer to which depends highly on whether Functions has member variables that are used in a() and b() or not. If there are no member functions, then declaring the a() and b() members as static will work. On the other hand, if you want to use a "member function pointer", the syntax is int (Functions::*f) and &Functions::a respectively, and the call has to be made using an instance of Functions. so if we have Functions fun, you'd do fun.*f(). Or (*this).*f(), insice F().

You may wrap the accepted function in a class:
#include <iostream>
class Functions
{
public:
int a() { return 0; }
int b() { return 1; }
};
class Accept
{
public:
typedef int (Functions::*AcceptFunction)();
int apply(Functions& object, AcceptFunction function) {
return (object.*function)();
}
};
int main()
{
Functions functions;
Accept accept;
std::cout << accept.apply(functions, &Functions::b) << std::endl;
}
(Feel free to bundle it by making Functions a nested class in Accept)

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

Calling Member Function Pointers

I am having trouble calling a function pointer inside a structure. I have used this approach before outside of classes, but now that I am trying it inside a class method using function pointers to other class methods.... I am receiving a compiler error. Here is my class:
class Myclass
{
int i;
void cmd1(int)
{}
void cmd2(int)
{}
void trans()
{
const struct
{
std::string cmd;
void (Myclass::*func)(int)
}
CmdTable[] =
{
{ "command1", &Myclass::cmd1 },
{ "command2", &Myclass::cmd2 }
};
CmdTable[0].func(i);
CmdTable[1].func(i);
}
};
The lines CmdTable[0].func(i); and CmdTable[1].func(i); both provide the following
error:
Error: expression must have (pointer-to-) function type.
I realize there are probably better ways of doing this, but I'm rather curious as to why what I've written doesn't work. Any explanation would be greatly appreciated.
The pointer-to-member-function is a pure class property. You need to combine it with a class instance in order to make a meaningful function call. For example, to use the instance *this, you can use the operator ->* and say:
(this->*CmdTable[0])(i);
Or you can use operator .* on an object value:
(*this.*CmdTable[0])(i);
The latter form is always correct. For the former, note that operator->* may be overloaded and do something unrelated.

How to use a class function pointer in another class or struct?

I need to use a function defined in one class in another class. Instead of rewriting the whole function, I tried to pass the function as a pointer, as below:
class C {
public:
int get(int x) { return x*x; }
};
struct S {
int (*func) (int x);
};
int main() {
C c;
S s;
cout << c.get(3) << endl;
s.func = &C::get;
cout << s.func(3) << endl;
return 0;
}
This doesn't work and gives the following error:
func_ptr.cpp: In function ‘int main()’:
func_ptr.cpp:42:18: error: cannot convert ‘int (C::*)(int)’ to ‘int (*)(int)’ in assignment
Is it possible to do something like this, and if so, how can I fix it? Moreover, if it is possible, can I use the pointer from an object instance instead of the class? That is, to possibly use variables defined in a specific class instance. Thanks.
C::get() is a non-static member function, which means it must be invoked on an instance of C. It has an implicit first argument, the this pointer, that must be passed to it when calling the function.
Since your C::get() doesn't seem to need access to any data members of C, you could make it a static member function.
static int get(int x) { return x*x; }
Now your code will work as is.
Another option is to change func so that it is a pointer to a member function of C
struct S {
int (C::*func) (int x);
};
And invoke it as
s.func = &C::get;
std::cout << (c.*(s.func))(3) << std::endl;
Yet another option would be to change the type of S::func to std::function<int(int)>. Now it can hold any callable (function pointer, functor, lambda) that takes a single int as an argument, and returns an int.
struct S {
std::function<int(int)> func;
};
s.func = std::bind(&C::get, &c, std::placeholders::_1);
std::cout << s.func(3) << std::endl;
A regular function and a member function are a bit different. To use a member function, you'll need an object to call it on (i.e. the this pointer in a member function body).
Take a look at std::function and std::bind, they are used to handle function like (callable) entities in a uniform way. They can manage global functions, static member functions, lambdas, regular member functions, functors, whatever that can be called like a function.
http://en.cppreference.com/w/cpp/utility/functional/function
http://en.cppreference.com/w/cpp/utility/functional/bind
http://en.cppreference.com/w/cpp/header/functional
e.g.:
struct S
{
std::function<int(int)> func;
};
C c;
S s;
s.func = std::bind( &C::get, &c, std::placeholders::_1 );
If you're OK with using STL then you can utilize std::function to hold a pointer to a function and std::bind to bind that particular pointer to a particular function. It makes your code look much more cleaner. std::bind looks for both static and non-static member functions. For non-static member function would need to pass the object reference so it will be able to point to the correct address.
Here is a code snippet to show how to use it:
std::bind(ClassName::MemberFunctionName, object, std::placeholders::_1)
std::placeholders::_1 means that ::MemberFunctionName accepts one parameter.

C++: Function pointer to another class function

I have 2 classes
class B {
public:
int func(int i);
};
class A {
public:
typedef int (B::*fPtr)(int);
void run();
B* mB;
};
void A::run() {
// create a pointer
fPtr p = &(B::func);
// invoke the function
mB->*p(2); <------- Compilation Error
}
What i need is to create a pointer to func() in A's run function. I get a compilation error saying that mB is not corresponding to a function with 1 argument.
please help
You need to put parentheses around the function expression:
(mB->*p)(2);
But as others have pointed out, there's almost certainly a better way to do what you're trying to do.
Instance methods on a class always have a hidden first parameter for the this pointer, thus it is incompatible with your function pointer typedef. There is no way directly to obtain a pointer to a member function. The typical workaround is to use a "thunk" where you pass a static function that accepts a generic "catch all" parameter (such as void *) which can be statically cast to a pointer of your choosing on which you can invoke the member function. Example:
class B
{
public:
static void MyThunk(void * obj)
{
static_cast<B *>(obj)->MyRealFunc();
}
void MyRealFunc()
{
// do something here
}
// . . .
};
You can get a pointer to the static function easily as it has no 'hidden this', just reference it using B::MyThunk. If your function requires additional parameters, you can use something like a functor to capture the necesssary parameters and state.
You should definitely read this C++ FAQ Lite page which tells you much more about all this: Pointers to member functions
why can you not call mB->func(2);?
If you need different functions for B perhaps look into virtual functions and class inheritance

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.