get state in a function object casted to a std::function - c++

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.

Related

this changes value in default and non-default constructor

I have a problem where I need to initialise a member object via a non-default constructor. However the compiler insists that I create a default constructor for the member object, which is called before the non-default constructor.
Consequently, the "this" pointer for the member object has different values in the default and non-default constructor but seems to stablise to the value in the default constructor.
I'm sure this is because I'm not using intialisation properly in C++, but I'm not sure what the correct way is to handle this.
Below is code which demonstrates the issue.
#include<iostream>
class my_object {
public:
my_object(int a) {
std::cout << "In non-default constructor for B\n";
std::cout << "Address of object is " << this << "\n\n";
}
my_object() {
std::cout << "In default constructor for B\n";
std::cout << "Address of object is " << this << "\n\n";
}
};
class my_first_object {
public:
my_first_object() {
std::cout << "In constructor for A\n";
std::cout << "The address of B is " << &B << "\n\n";
B = my_object(0);
std::cout << "We have just called the non-default constructor for B\n";
std::cout << "The address of B is " << &B << "\n\n";
}
my_object B;
};
int main() {
std::cout << "\n";
my_first_object A = my_first_object();
std::cout << "The address of A.B is " << &A.B << "\n";
return 0;
}
The output of this programme is
In default constructor for B
Address of object is 0x7ffee5d83ae8
In constructor for A
The address of B is 0x7ffee5d83ae8
In non-default constructor for B
Address of object is 0x7ffee5d83a90
We have just called the non-default constructor for B
The address of B is 0x7ffee5d83ae8
The address of A.B is 0x7ffee5d83ae8
You're loooking at this in two different objects - the second is created in the assignment
B = my_object(0);
which creates another my_object and assigns its value to B (which has already been created).
The only way to initialize members is to use the initializer list:
my_first_object() : B(0)
{
}
The reason for the compiler's insistence that you add a default constructor is that if you don't initialize a member in the initializer list, it is "default-initialized", and your code is equivalent to
my_first_object()
: B() // Initialization
{
B = my_first_object(0); // Assignment
}
Please see program here : http://cpp.sh/2oisg
You need to change, your my_first_object constructor like this:
my_first_object(int a = 0):B(a) {
std::cout << "In constructor for A\n";
std::cout << "The address of B is " << &B << "\n\n";
// B = my_object(0);
std::cout << "We have just called the non-default constructor for B\n";
std::cout << "The address of B is " << &B << "\n\n";
}
This way you are preventing a call to default constructor of my_object

Call copy constructor instead of move constructor?

I define a class A like this:
class A {
public:
A(){
cout << "A constructing..." << endl;
}
A(const A &a){
cout << "A copy constructing..." << endl;
}
A(A&& a){
strcpy(name, a.name);
cout << "A move constructing..." << endl;
}
~A(){
cout << "A destructing..." << name << endl;
}
};
And a simple function:
A f(A&& b) {
cout << "------after call------" << endl;
A f = b; // Use "A f(b)" to get the same effect
cout << "------before return------" << endl;
return f;
}
And when I call auto test = f(move(b));, why would it call copy constructor instead of move constructor? Is b in f() not a rvalue?
Nope, the expression b in the body of f is an lvalue. The name of a variable is always an lvalue, even if the variable's declaration has rvalue reference type.
This rule exists because otherwise it would be a little too easy to accidentally move from a variable before you want:
void validate(A obj);
void f(A&& b) {
A a1 = b;
// Maybe some other code in between.
A a2 = b;
}
Even though some A rvalue expression was passed to f, once inside f it has a name, so the object can be used more than once. If we copy instead of move both times, at least that's safer than moving then trying to use the moved-from variable.
So use std::move on an rvalue reference variable name when you know it's the last time you need the variable's value, to explicitly tell that context it's okay to move.

C++; using lambdas to conditionally expand a function within a class (seg fault with MWE)

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;};
}

why don't I get return value optimization in this code?

Could anyone explain to me the 5th line of the output? I don't understand why the MyClass object b doesn't get assigned returned object c from the func.
class MyClass
{
public:
int x;
std::string s;
MyClass(const MyClass &other);
MyClass();
void output();
};
MyClass::MyClass(const MyClass &other): x(2), s("s?") { }
MyClass::MyClass() : x(1), s("s1") { }
void MyClass::output() { cout << x << " " << s << endl; }
MyClass func(MyClass c) //MyClass c = Myclass(a)
{
cout << "2. in func: "; c.output();
c.s = "s2";
cout << "3. in func: "; c.output();
return c;
}
int main()
{
MyClass a;
cout << "1. "; a.output();
MyClass b = func(a);
cout << "4. "; a.output();
cout << "5. "; b.output();
}
The output is:
1. 1 s1
2. in func: 2 s?
3. in func: 2 s2
4. 1 s1
5. 2 s?
I understand where do lines 1-4 come from, but I don't get why at the end, the MyClass b.s has a value of s? not the s2. Is it because the const object is created within the func scope?
EDIT:
I know that the copy constructor is called when MyClass c object is initialized within the func scope, but how the returned object is not assigned to b ?
MyClass b = func(a);
That line will call the copy constructor of MyClass to create b from a. Although it has an =, it does not call the assignment operator; the object hasn't been created yet, so there's nothing to assign to.
An object doesn't need to be const to bind to a const T&, even temporaries can bind to them.
why don't I get return value optimization in this code?
The reason is that your function is returning c, which is a parameter. Even though it is a value, and therefore a local object in the function, this is one of the cases in which return value optimization (in this case, named return value optimization, or NRVO) is not permitted by the C++ standard. If you were to create a local copy of c, RVO would be allowed:
MyClass func(MyClass c) //MyClass c = Myclass(a)
{
MyClass d = c;
cout << "2. in func: "; d.output();
d.s = "s2";
cout << "3. in func: "; d.output();
return d;
}
With those changes, I get the following using a recent clang++:
1 s1
in func: 2 s?
in func: 2 s2
1 s1
2 s2
You return a local variable c in func. It gets copy constructed, to be copied into b. Your copy constructor specifies s="s?" so that's what it's being set as.

Inheritance: why is there a difference in behaviour between inherited and supplied variables?

For example, in this piece of code, if line [a] is commented out, the output is 0.
inh2.cpp
#include<iostream>
using namespace std;
class A {
public:
int x;
A() { x = 10; }
};
class B : public A {
public:
int x; // <--------- [a]
B() { x = 0; }
};
int main() {
A* ab = new B;
cout << ab->x << endl;
}
results from gcc
$ g++ inh2.cpp
$ ./a.out
10
$
I have two questions:
How does ab->x resolve to 10 in the above case? The object is of type class B, and thus should value to 0.
Why does commenting Line [a] change the behaviour of the code? My reasoning is that x would have anyways been inherited, which should result in same behaviour.
My reasoning for Q #1 above:
ab points to the memory location of an object of class B. It is a physical object in the sense that all the variables with their values are assigned memory.
Variable x within this object stores value 0.
When ab->x is done, ab tells us the memory location of the object, and we go look inside it to find that x is 0. So we should print 0.
Where am I wrong here?
Yes, it is of type B, but you are assigning it as a pointer to an A, and therefore it is using the x defined on A (as when we're dealing with a pointer to A, we don't know that B even exists, even though that's what you allocated).
When you comment out the line, during the construction phase, As constructor is called first, then Bs constructor, which sets x (in its base class) to 0. There is only one x at this point, and Bs constructor is called last.
Making a some small modifications:
#include <iostream>
using namespace std;
class A {
public:
int x;
A()
:x(10)
{
std::cout << __FUNCTION__ << std::endl;
std::cout << x << std::endl;
}
virtual ~A() {}
};
class B : public A {
public:
int x; // <--------- [a]
B()
:A()
,x(0)
{
std::cout << __FUNCTION__ << std::endl;
std::cout << x << std::endl;
}
};
int main() {
A* ab = new B;
cout << "ab->x: " << ab->x << endl;
cout << "ab->A::x " << ab->A::x << endl;
B* b = dynamic_cast<B*>(ab);
cout << "b->x: " << b->x << endl;
cout << "b->A::x " << b->A::x << endl;
cout << "b->B::x " << b->B::x << endl;
}
This gives you:
A
10
B
0
ab->x: 10
ab->A::x 10
b->x: 0
b->A::x 10
b->B::x 0
This demonstrates that:
ab->x refers to A::x because ab is of type A* and there is no such thing as a virtual variable. If you want polymorphism, you'll have to write a virtual int get_x() const method.
B::x hides A::x. This is a bad idea and should be avoided. Consider using a more meaningful name for your member variables and establish whether you can reuse the base class's variable before introducing a new one.
Casting to a B* allows you access to B's members as well as A's. This should be self-explanatory.