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
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.
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
Why are we able to call the showA() method without object? But if I use void A::showA(A& x) in the method definition then I have to call it using A's object, why?
#include <iostream>
class A {
public:
int a;
A() { a = 0; }
void showA(A&);
};
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
int main()
{
A a;
showA(a);
return 0;
}
Why are we able to call the showA() method without object?
You don't call the member function A::showA, but instead the free function showA. In fact, the member function A::showA(A&) is declared, but never defined, only the free function showA(A&) has a definition.
If you want to call A::showA, you need a definition;
void A::showA(A& x) { /* ... */ }
// ^^^ this makes it a member function definition
and then call it as
A a;
a.showA(a);
(Note that it doesn't make much sense to pass the a instance to A::showA invoked on the identical a instance, but that's another issue).
This function
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
is not a member function of the class A.
It accepts one argument of the type A &.
As for the member function showA then it is declared but not defined.
You could declare it within the class like
class A {
public:
int a;
A() { a = 0; }
void showA() const;
};
and then define it outside the class definition like
void A::showA() const
{
std::cout << "A::a=" << a;
}
In this case the function main can look like
int main()
{
A a;
showA(a);
a.showA();
return 0;
}
You can't call it because showA(the one you are thinking) is not the part of the class.It is a global function.The showA function which you declared in class was never defined. In order to do so modify your code a bit.
Change this piece of code.
void A::showA(const A& x) {
std::cout << "A::a=" << x.a; } // It is advised to make const as it doesn't change state.
I have a simple class X
class X {
public:
template<typename T>
void doSomething(T &completion) {
std::cout << completion(10) << std::endl;
}
};
and a class A and B
class A {
public:
// some code
X* c;
};
class B : public A {
public:
int test(int x) {
return x * x;
}
void execute() {
auto lambda = [] (int x) { cout << x * 50 << endl; return x * 100; };
c->doSomething(lambda); // works
c->doSomething(&B::test); // does not work
}
};
I want to pass to the doSomething method a member method of class B (or any other class derived from A) but it just does not work :/
How can I pass a member function from a derived class as a callback?
Your problem has nothing to do with B being a child class. Your problem is that you're not binding the non-static member function test() to its instance.
You can address this easily, either by using std::bind to return a functor:
c->doSomething(std::bind(&B::test, this, std::placeholders::_1));
and don't forget to #include <functional>,
or use a lambda to wrap the call by putting this in the lambda captures:
c->doSomething([this](int x){ return this->test(x); });
Note: Make sure to change doSomething()'s parameter to be a rvalue reference so it could properly take all this callback goodness in both temporary objects and otherwise. Should look like this:
template<typename T>
void doSomething(T&& completion)
Make B::test a static method and it will work as written:
static int test(int x) {
return x * x;
}
// ...
c->doSomething(&B::test);
This is because a static method doesn't require an implicit instance (a this pointer).
If B::test must be a regular method, then you must pass the instance by using a capturing lambda, like this:
c->doSomething([this] (int x) { return this->test(x); });
NOTE: when getting this code to compile, I needed to change your definition of doSomething to leave the & off of T:
template<typename T>
void doSomething(T completion) {
std::cout << completion(10) << std::endl;
}
This prevents putting a l-value, or non-const, constraint on the function pointer type, which can prevent the compiler from creating a temporary lambda function.
Do you mean c->doSomething([this](int x) { return this->test(x); }); ?
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
}