I want to save lambda expressions variables (like in the fist code block). The problem is that then I use a classes (like the second code block) the compiler return me some errors. I don"t know how to fix it.
I hope somebody can help me and explain, why it's not working like this. Thanks.
First Code:
// variable for function pointer
void (*func)(int);
// default output function
void my_default(int x) {
cout << "x =" << "\t" << x << endl << endl;
}
int main() {
cout << "Test Programm\n\n";
// 1. Test - default output function
cout << "my_default\n";
func = &my_default;
func(5);
// 2. Test - special output function 2
cout << "my_func2\n";
func = [](int x) { cout << "x =" << " " << x << endl << endl; };
func(5);
return 0;
}
Second Code:
class test {
private:
// variable for function pointer
void (*func)(int);
// default output function
void my_default(int x) {
cout << "x =" << "\t" << x << endl << endl;
}
public:
void dummy(void) {
// 1. Test - default output function
cout << "my_default\n";
func = &my_default;
func(5);
// 2. Test - special output function 2
cout << "my_func2\n";
func = [](int x)->int{ cout << "x =" << " " << x << endl << endl; };
func(5);
}
};
// entry
int main() {
cout << "Test Programm\n\n";
test a;
a.dummy();
return 0;
}
Compiler:
pi#raspberrypi ~/dev/property $ gcc -std=c++0x -o test2 test2.cpp -lstdc++
test2.cpp: In member function ‘void test::dummy()’:
test2.cpp:491:17: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say ‘&test::my_default’ [-fpermissive]
test2.cpp:491:17: error: cannot convert ‘void (test::*)(int)’ to ‘void (*)(int)’ in assignment
test2.cpp:496:77: error: invalid user-defined conversion from ‘test::dummy()::<lambda(int)>’ to ‘void (*)(int)’ [-fpermissive]
test2.cpp:496:28: note: candidate is: test::dummy()::<lambda(int)>::operator int (*)(int)() const <near match>
test2.cpp:496:28: note: no known conversion for implicit ‘this’ parameter from ‘int (*)(int)’ to ‘void (*)(int)’
The problem is that member functions are not normal functions, they can't be assigned to a function pointer because the type in which they are member is part of their type.
Also, a member function needs to have an object to be called on, which will be the this inside the function code.
You have several solutions:
allow only functions which are member of your class
void (*MyClass::func)(int); // but you can use it only with members of the class
use std::function
typedef std::function<void(int)> func;
The solution 2 is the simplest as std::function is designed to work with anything that is callable with the same signature as the one in the template parammetters.
Also, it's the only solution that allows you to store closures(objects from lambdas).
See C++11 styled callbacks? for details.
class test {
private:
// variable for function pointer
std::function< void ( int )> func;
// default output function
void my_default(int x) {
cout << "x =" << "\t" << x << endl << endl;
}
public:
void dummy(void) {
// 1. Test - default output function
cout << "my_default\n";
func = std::bind(&test::my_default, this, std::placeholders::_1);
// or
func = [&]( int i ){ my_default( i ); };
func(5);
// 2. Test - special output function 2
cout << "my_func2\n";
func = [](int x)->int{ cout << "x =" << " " << x << endl << endl; };
func(5);
}
};
// entry
int main() {
cout << "Test Programm\n\n";
test a;
a.dummy();
return 0;
}
A member function is not like an ordinary function, in that there has to be an instance of the class available in order to invoke it (i.e., the object that will become *this). You can't make an ordinary function pointer variable point to a member function.
If you want to create a function pointer that can be called using any instance of the class, you need a member function pointer. You would write
void (test::*func)(int);
to declare it,
func = &test::my_default;
to assign it, and
(this->*func)(5);
to call it. Of course, now you can't make a member function pointer point to a lambda.
If on the other hand you want to bind this as the instance and create an ordinary function from a member function, well, you can't actually make an ordinary function pointer to it. Instead you'll want an std::function object,
std::function<void(int)> func;
bind as follows:
func = std::bind(&test::my_default, this, std::placeholders::_1);
and then call normally. std::function works with lambdas just like a function pointer would.
Related
I would like to use lambdas to conditionally expand the functionality of a function within a class. There is no problem doing this outside of the class scope (see example), but the minimal working example below leads to a segmentation fault when calling a function that has modified itself within the class. Can anyone explain why this code fails and how I should be thinking about lambdas within a class differently than lambdas outside of a class?
#include <functional>
#include <iostream>
class MyClass
{
public:
MyClass(bool modify);
int a;
std::function<void (void)> myFunc;
};
MyClass::MyClass(bool modify)
{
a = 2;
myFunc = [this](){ std::cout << "1. Inside my initialized function; a="
<< this->a << std::endl;};
//myFunc(); -- works with or without being commented
if (modify)
{
myFunc = [this](){ this->myFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
//EDIT: Originally tried
// myFunc = [myFunc](){ myFunc(); std::cout << endl; };
// but this will not compile. See edit of post below
//myFunc(); -- fails with or without being commented
}
}
int main(int argc, char **argv)
{
std::function<void (void)> func;
int a = 2;
func = [a](){ std::cout << "1. Inside my initialized function; a="
<< a << std::endl;};
func = [func](){ func();
std::cout << "2. adding an output line to my initialized "
<< "function" << std::endl;};
std::cout << "Result of modified function outside of class: " << std::endl;
func();
std::cout << std::endl;
std::cout << "Result of unmodified function in class: " << std::endl;
MyClass myClassNoMod(false);
myClassNoMod.myFunc();
std::cout << std::endl;
std::cout << "Result of modified function in class: " << std::endl;
MyClass myClassMod(true);
myClassMod.myFunc();
return 0;
}
Edit PaulR gave the reasonable suggestion of capturing myFunc rather than this in the update of myFunc. In my original implementation this is what I tried:
myFunc = [myFunc](){myFunc(); std::out << "stuff\n"; };
but this lead to the compiler errors
error: 'myFunc' in capture list does not name a variable
myFunc = [myFunc](){ myFunc();
^
error: 'this' cannot be implicitly captured in this context
myFunc = [myFunc](){ myFunc();
In your class you capture the this pointer and not the previous value of myFunc, thus your lambda will recursively call itself forever, since at call time the myFunc member will be already changed to the new lambda.
In main you capture the previous value of func by value and thus it does what you expect.
So I would suggest capturing a copy of myFunc by value (i.e. without &) instead of this.
if (modify)
{
auto previousFunc = std::move(myFunc);
myFunc = [previousFunc](){ previousFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
}
If you are using C++14 or newer you can also use lambda capture expressions to avoid making a copy and directly moving the previous function into the lambda capture:
if (modify)
{
myFunc = [previousFunc{std::move(myFunc)}](){ previousFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
}
class Test{
public:
int work(){
cout << "in work " << endl;
return 0;
}
void work(int x){
//cout << "x = " << x << endl;
cout << "in work..." << endl;
}
};
int main(){
Test test;
std::function<void()> f = std::bind(&Test::work, &test);
thread th(f);
th.join();
return 0;
}
As above code, I want to bind member function void work(void) of a class (let's name it Test) , but occurs compiler error saying that can not determine which overrided function to use.
I can not change class Test since it belongs to a lib, how to achieve my goal? Thanks in advance!
Why don't skip std::bind altogether and use a lambda?
auto fp = [&t]() { t.test()};
As a bonus, your executable size will be smaller and your compiler has much easier time to inline the code if appropriate.
By casting it to the correct type:
std::function<void()> f = std::bind( static_cast<int (Test::*)()>(&Test::work), &test);
When deducing the template arguments to bind, the compiler is not in a context that allows function overload resolution - to be simplistic about it, it hasn't got that far yet.
Having deduced that the first argument is indeed the name of a member function pointer, it finds that there are two functions of the same name but of different types.
At this stage, they're both equally valid candidates (from the point of template argument deduction), therefore it's ambiguous
A static cast disambiguates because we're pushing the compiler beyond the stage where it has to deduce a template type - we have taken on the responsibility to template type deduction ourselves - by specifying the type in the static_cast.
So now all it has to do is overload resolution.
#include <functional>
#include <thread>
#include <iostream>
using namespace std;
class Test{
public:
int work(){
cout << "in work " << endl;
return 0;
}
void work(int x){
//cout << "x = " << x << endl;
cout << "in work..." << endl;
}
};
int main(){
Test test;
// only overload resolution required here
auto fp = static_cast<int (Test::*)()>(&Test::work);
// type is now unambiguous and overload resolution is already done
std::function<void()> f = std::bind(fp, &test);
thread th(f);
th.join();
return 0;
}
try this(member function ptr):
int main(){
Test test;
typedef int(Test:: *WKPtr)(void);
WKPtr p = &Test::work;
std::function<int()> f = std::bind(p, &test);
f();
return 0;
}
I'm so confused, why I can't access void func(int i), anybody can help me?
Of course this is just a demo to help your understand my question easily. Its real code is huge, I want the member functions in Base and Child both available.
The output always is
**
double
2
**
struct base
{
void func(int i)
{
cout << "int" << endl;
cout << i << endl;
}
};
struct child : base
{
void func(double d)
{
cout << "double" << endl;
cout << d << endl;
}
};
child c;
c.func((int)2);
Because child::func hides base::func.
You need to either make it visible in the derived class by bringing the name in scope:
struct child : base
{
using base::func;
void func(double d)
{
cout << "double" << endl;
cout << d << endl;
}
};
or call the base version explicitly by qualifying the name at the call site:
c.base::func(2);
The implicit conversion from int to double is masking the actual problem. If you change your base class func parameter type from int to string:
struct base
{
void func(string i)
{
cout << "string" << endl;
cout << i << endl;
}
};
Then you'd receive the following error to make it clearer:
func.cpp: In function `int main()':
func.cpp:27: error: no matching function for call to `child::func(const char[13])'
func.cpp:17: note: candidates are: void child::func(double)
Where you can see it only has visibility of child::func not base::func
struct Widget {
void test() {}
};
int func() {}
int main() {
std::cout << &Widget::test << std::endl;
std::cout << Widget::test << std::endl;
std::cout << func << std::endl;
std::cout << &func << std::endl;
}
In this code only the second line of main function doesn't compile. The others print 1. Why does it print 1. Shouldn't print the address of function? And why second doesn't compile but first does?
Why does it print 1. Shouldn't print the address of function?
No. std::cout can print a void*, but there's no implicit conversion from function pointer types to void* (for neither regular function pointers nor pointer-to-member types). There's a conversion from function pointer types to bool though. That's what we end up with.
And why second doesn't compile but first does?
Because the standard requires you to use & to get the address of a member function.
I want to retrieve state from a function object. But the function object has been casted to a function<> template. How can I do it?
I mean:
function object:
class Counter {
private:
int counter_;
public:
Counter():counter_(0) {cout << "Constructor() called" << endl;}
Counter(int a):counter_(a) {cout << "Constructor(a) called" << endl;}
void operator()(int sum) {
cout << counter_++ + sum << endl;
}
int getCounter() { return counter_;}
};
In main. My first step is use object directly:
int main() {
Counter a(10);
a(0);
a(0);
cout << "Counter: " << a.getCounter() << endl;
Its shows:
Constructor(a) called
10
11
Counter: 12
It's ok and it's what I expected.
But in
Counter b(10);
function<void(int)> f = b;
f(0);
f(0);
cout << "Counter: " << b.getCounter() << endl;
It shows
Constructor(a) called
10
11
Counter: 10
Argh!, I supposed that f was a wrapper of real object so modifying f we really modify b. No: f has a copy of b, but I can't call to f.getCounter() so How can I get State (counter_ var) from f?
I can't use directly Counter class (in this example) because I have some other similar classes with same signature "void(int)" And I want to use them in indistinctly in a caller function.
I can avoid std::function template at all using a common base class for all my function object but I think there is a solution more C++11 with STL and templates...
So, Is there that solution?
Thanks
Create the function from a reference wrapper:
function<void(int)> f = std::ref(b);
giving the result:
Constructor(a) called
10
11
Counter: 12
Of course, you need to make sure that the function isn't invoked after the counter is destroyed.
If you need to access the counter from the function object, then use its target member:
if (Counter * c = f.target<Counter>()) {
std::cout << "Counter: " << c->getCounter() << '\n';
} else {
std::cout << "Not a counter.\n";
}
This is not a cast:
function<void(int)> f = b;
A std::function is been constructed, with a copy of your function object as its target.
You can either make the target a reference to your function object:
function<void(int)> f = std::ref(b);
Or let f contain a copy but then retrieve that copy from f:
Counter* c = f.target<Counter>();
cout << "Counter: " << c->getCounter() << endl;
It's usually safer to let f contain a copy as you don't ned to worry about the lifetime of b.