I am trying to build a class that has a member function with a method as argument. The methods are defined in inherited classes. I build a minimal example:
#include <iostream>
struct base
{
base() {}
int number(int (*f)(int))
{
return f(1);
}
};
struct option1 : base
{
int timesTwo(int i){return 2*i;}
option1()
{
std::cout << number(timesTwo);
}
};
struct option2 : base
{
int timesThree(int i){return 3*i;}
int timesFour (int i){return 4*i;}
option2()
{
std::cout << number(timesThree);
}
};
int main()
{
option1 a; //I would expect this to print "2"
}
The current syntax in the function number is for a general function, but I cannot get it to work for a method of any inherited classes.
The problem here is that you're passing a pointer to a member function, which is completely different from a pointer to a non-member function (which is what your number function takes as an argument).
You could use std::function and std::bind:
int number(std::function<int(int)> f)
{
return f(1);
}
...
number(std::bind(&option1::timesTwo, this, _1));
You could also use templates, and extra arguments, like
template<typename T>
int number(T* object, int(T::*f)(int))
{
return (object->*f)(1);
}
...
number(this, &option1::timesTwo);
Or the simple (but not always correct, depending on situation and use case): Make the callback-function static:
static int timesTwo(int i){return 2*i;}
My recommendation is that you look over the solution using std::function, because then it's easy to call the number function with any type of callable object, like a lambda:
number([](int x){ return x * 2; });
The given error says :
error: reference to non-static member function must be called
You can just add static before your method members.
And I would suggest you to use std::function instead of pointer functions.
A working code :
#include <iostream>
#include <functional>
struct base
{
base() {}
int number(std::function<int(int)> f)
{
return f(1);
}
};
struct option1 : base
{
static int timesTwo(int i){return 2*i;}
option1()
{
std::cout << number(timesTwo);
}
};
struct option2 : base
{
static int timesThree(int i){return 3*i;}
static int timesFour (int i){return 4*i;}
option2()
{
std::cout << number(timesThree);
}
};
int main()
{
option1 a; // now it works
}
Related
I have a class A which has a constructor with a function argument: i.e.
class A {
public:
A(int (*f)(int);
};
I can create this class and have it use func() with, for example,
int func(int n);
A a(func);
I would like to invoke this class a number of times, but have it use internally func(n)+m instead of func(n). I would prefer not to change class A. I could create a new class to define the function I want
class B {
int (*func)(int n);
int m;
public:
B(int (*ff)(int),int mm) : func(ff),m(mm) {}
int myfunc(int n) { return(func(n)+m);
};
However, I don't think it is possible to convert a pointer to myfunc into a pointer with the required signature for A's constructor.
The way I have chosen is similar to the above, but with myfunc() and associated variables stored in the global space:
int m;
int (*func)(int);
int myfunc(int n) { return(func(n)+m); }
void setupmyfunc(int mm,int (*ff)(int)) { m=mm; func=ff; }
Then I can can create my A object with
setupmyfunc(m,func);
A a(myfunc);
This works, but seems inelegant to me. Is there a better way?
Stateless lambdas are implicitly convertible to function pointers so you can just use that without modifying your class A and without creating another class B. That is if I understood your question correctly.
class A {
public:
A(int (*f)(int)) {};
};
int func(int n) { return n * 10; }
auto test()
{
A a{[](int n) { return func(n) + 1; }};
}
std::function can hold callable objects (functions, function objects, member function pointers (with object to bind to), etc. It uses some type-erasure such that it can have this genericity, but comes at the cost of internal overhead to actually invoke it, often equivalent to a virtual function call.
Here's an example, where A takes a std::function, which allows you to pass in lambdas.
#include <functional>
#include <iostream>
class A {
std::function<int(int)> func_;
public:
A(std::function<int(int)> func) : func_(func) {}
int call(int x) {
return func_(x);
}
};
int foo(int x) {
return x * 123; // whatever
}
int main() {
// here's your wrapper function to do func(x)+m (m==9 in this case)
A obj([](int x) { return foo(x) + 9; });
int result = obj.call(123);
std::cout << result << '\n';
}
https://godbolt.org/z/94MfGM67K
Update:
Given the rejection of both answers so far, using std::function is out because it changes class A, and the obvious use of state-full lambdas for composition and capturing customization data is also out, you will need to get more creative and possibly ugly. If you can't change A, then you can't change the signature of the function passed to a, so making the lambda take its data as another argument is also out.
Seems to me that leaves just one thing: using state that is outside the function (i.e. global data or encoded in a template non-type template parameter) as a form of pseudo-capture that an otherwise stateless function can use. I reject the global approach in general, though there's interesting aspects to it, and only present a template solution:
Now you write your free-standing functions and can compose them with a template:
#include <iostream>
using F = int(*)(int);
class A {
public:
A(F f) : f_(f) { }
int operator()(int x) { return f_(x); } // Added for demo
private:
F f_;
};
template <F FuncF, F FuncG>
int compose(int n) {
return FuncF(FuncG(n));
}
int func(int n) { return n * 1000; }
int add888(int n) { return n + 888; }
int add999(int n) { return n + 999; }
int main() {
A a1(compose<add888, func>);
A a2(compose<add999, func>);
std::cout << a1(1) << " " << a2(1) << " " << a1(1);
}
// output: 1888 1999 1888
https://godbolt.org/z/8KsqbTcTd
This works as far back as c++11, and replacing the "using" with "typedef" it work in C++98.
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
}
Let's say, I have a class:
class A {
int a;
};
And I have a lambda:
auto function = [](A* a) {
a->a; // <== gives an error in this line.
};
function(new A);
Is there any way to use a private member/method inside a lambda? - It's not necessary to pass the pointer to the lambda - it may be a capture-by or something else.
All reasonable schemes are welcome.
You can do it by creating a friend function that returns the lambda function. It inherits the friend access:
struct A {
friend std::function<void(A&, int)> f();
private:
int i;
void test() {std::cout << "test: " << i << "\n";}
};
std::function<void(A&, int)> f() {
return [] (A &a, int i) {a.i = i; a.test(); };
}
int main() {
A a;
f()(a, 13);
return 0;
}
In order to make a lambda a friend, you need to befriend a class or a function where the lambda is defined. Here is a complete example:
#include <iostream>
using namespace std;
class A {
int a;
public:
A(int _a) : a(_a) {}
friend int foo(A*); // Declare foo(A*) a friend of A
};
int foo(A* aa) {
auto function = [](A* a) {
return a->a; // Now foo(A*) can access A::a, which is private
};
return function(aa);
}
int main() {
A a(123);
cout << foo(&a) << endl;
return 0;
}
Here is a running demo on ideone.
using std::function takes extra resource, so I recomendet using friend/or method function to access private member (friend function implicit inlined):
class A{
int a;
friend int access_member(A*a){ return a->a;}
};
-----------------------------------------
auto function = [](A*a){ return access_member(a); }
Live example
EDIT: I personally like std::function, but don't forgot, std::function always takes extra memory resources, and may not inlined , so if you may implement your source without std::function, don't use std::function. See, How is std::function implemented?
Also, Lambda to std::function conversion performance
I want to pass a method as an argument to a method which takes an int and returns void:
void A::SetCallback(void (*callback)(int))
{
.....................
}
void B::test()
{
a->SetCallback(&B::Done); //
}
void B::Done(int i)
{
..........................
}
Inside test() I get this error:
Error 1 error C2664: cannot convert parameter 1 from 'void (__thiscall B::* )(int)' to 'void (__cdecl *)(int)'
I saw some example on StackOverflow how to fix this but it uses elements from C++11, to which I do not have access.
How can I fix this using C++03 ?
You cannot pass a non-static method to a function that takes a pointer to a function. Functions and methods are two completely different things. In order to invoke a non-static method you have to, obviously, have an object whose method you're invoking.
If, in your example, Done() is a static class method, then, yes, you can pass it this way, since a static class method is just another name for a function.
It is possible to have a pointer to a class method:
void A::SetCallback(void (B::*callback)(int))
{
}
void B::test()
{
a->SetCallback(&B::Done); //
}
void B::Done(int i)
{
..........................
}
But in order to invoke the class method, you need an object whose method to invoke:
B *object=give_me_a_pointer_to_b_from_somewhere();
(object->*callback)(0);
&ClassName::method_name creates the pointer and void(ClassName::*)(int, char*) is the type.
void go(void(ClassName::*parameter_name)(int, char*));
go(&ClassName::method_name);
You cannot pass a pointer to class method (which is of type void (B::*) (int) in your case) to a pointer to a free function.
What would happen if you could?
void f (void (*g) (int)) {
g(2);
}
struct A {
int x;
void foo (int c) { x += c; }
};
f(&A::foo); // Oh oh! Where will I find `x` in the call `g(2)`?
If you only want pointer to method of B, you need to change the callback type:
void A::SetCallback(void (B::*callback)(int)) { }
But then you need an instance of B to call your callback, e.g.:
B b;
(b.*callback)(2);
I'm using following code. It is not pretty, but you asking for C++03:
#include <iostream>
#include <vector>
#include <functional>
class AbstractCallback {
public:
virtual void call(int arg) = 0;
};
template <class T>
class Callback : public AbstractCallback {
public:
typedef std::mem_fun1_t<void, T, int> CallbackFunc;
private:
CallbackFunc func;
T* object;
public:
Callback(T* _object, const CallbackFunc& _func)
: object(_object), func(_func) {
}
void call(int arg) {
func(object, arg);
}
};
struct A {
void foo(int a) {
std::cout << "foo " << a << std::endl;
}
};
struct B {
void bar(int a) {
std::cout << "bar " << a << std::endl;
}
};
int main() {
A a;
B b;
AbstractCallback* cbs[2] = {
new Callback<A>(&a, std::mem_fun(&A::foo)),
new Callback<B>(&b, std::mem_fun(&B::bar)),
};
cbs[0]->call(10);
cbs[1]->call(22);
delete cbs[0];
delete cbs[1];
return 0;
}
As you can see pointer-to member functions (of type A::* and B::*) are wrapped into std::mem_funs and a Callback class which is generated for each type (A and B in this case).
This allows to keep method of any type in vectors, arrays or lists of abstract callbacks.
Let's say, I have a class:
class A {
int a;
};
And I have a lambda:
auto function = [](A* a) {
a->a; // <== gives an error in this line.
};
function(new A);
Is there any way to use a private member/method inside a lambda? - It's not necessary to pass the pointer to the lambda - it may be a capture-by or something else.
All reasonable schemes are welcome.
You can do it by creating a friend function that returns the lambda function. It inherits the friend access:
struct A {
friend std::function<void(A&, int)> f();
private:
int i;
void test() {std::cout << "test: " << i << "\n";}
};
std::function<void(A&, int)> f() {
return [] (A &a, int i) {a.i = i; a.test(); };
}
int main() {
A a;
f()(a, 13);
return 0;
}
In order to make a lambda a friend, you need to befriend a class or a function where the lambda is defined. Here is a complete example:
#include <iostream>
using namespace std;
class A {
int a;
public:
A(int _a) : a(_a) {}
friend int foo(A*); // Declare foo(A*) a friend of A
};
int foo(A* aa) {
auto function = [](A* a) {
return a->a; // Now foo(A*) can access A::a, which is private
};
return function(aa);
}
int main() {
A a(123);
cout << foo(&a) << endl;
return 0;
}
Here is a running demo on ideone.
using std::function takes extra resource, so I recomendet using friend/or method function to access private member (friend function implicit inlined):
class A{
int a;
friend int access_member(A*a){ return a->a;}
};
-----------------------------------------
auto function = [](A*a){ return access_member(a); }
Live example
EDIT: I personally like std::function, but don't forgot, std::function always takes extra memory resources, and may not inlined , so if you may implement your source without std::function, don't use std::function. See, How is std::function implemented?
Also, Lambda to std::function conversion performance