c++ operator int is called in the code why? - c++

In the below code snippet
#include <iostream>
class A
{
public:
A(int i) : m_i(i) { }
public:
int operator()(int i = 0) const
{
return m_i + i;
}
operator int () const
{
return m_i;
}
operator float () const
{
return 0.0;
}
private:
int m_i;
friend int g(const A&);
};
int f(char c)
{
return c;
}
int g(const A& a)
{
return a.m_i;
}
int main()
{
A f(2), g(3);
int i = f;// call 1
std::cout << f(1) << g(f) << std::endl;// call 2
return 0;
}
I gave some comments like call 1 and call 2 in the main function.
I understood why operator int is called at call 1.
But I could not understand why at // call 2
Can some body explain me why it is so.

The function g is hidden by the g (of type A) in scope. So g(f) converts f to int then calls g.operator()(int) with the result of the conversion.

When you call g(f), A::operator()(int i=0) is called for g.
f must therefore be converted into an int, which is done via A::operator int() .

std::cout << f(1) << g(f) << std::endl;
Let's break this down into function calls instead of operators. (This might not be technically correct syntax.)
int temp1 = f.operator()(1);
ostream& temp2 = std::cout.operator<<(temp1);
// By the implementation of ostream::operator<<, temp2 is a reference to std::cout.
// The compiler doesn't know this, though, and must treat it as if it could be different.
int temp3 = f.operator int(); // Typecast since A::operator() expects an `int`.
int temp4 = g.operator()(temp3);
ostream& temp5 = temp2.operator<<(temp4);
// temp5 is another reference to std::cout.
temp5.operator<<(std::endl);
// Result discarded.

Related

Can I set a value using a function in a class?

If I have a friend function can I somehow use set() to assign a value to a private variable inside the function? Or some other method?
Example : Here I have 3 private variables. I tried to make the sum of 2 of them and store the result in the 3rd one. I tried to do it with a setter but the result is 0. In main it works, but I don't know if I can make it work in the class function.
#include <iostream>
using namespace std;
class Function{
private:
int a;
int b;
int sum;
public:
Function() = default;
Function(int _a, int _b);
friend int sumNumber(Function f);
//Setter and getter
int getA() const;
void setA(int a);
int getB() const;
void setB(int b);
int getSum() const;
void setSum(int sum);
};
Function::Function(int _a, int _b) {
this->a = _a;
this->b = _b;
}
int Function::getA() const {
return a;
}
void Function::setA(int a) {
Function::a = a;
}
int Function::getB() const {
return b;
}
void Function::setB(int b) {
Function::b = b;
}
int Function::getSum() const {
return sum;
}
void Function::setSum(int sum) {
Function::sum = sum;
}
int sumNumber(Function f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
int main() {
Function AA(1,2);
cout << sumNumber(AA);
cout << " " << AA.getSum();
AA.setSum(sumNumber(AA));
cout << "\n" << AA.getSum();
return 0;
}
Output :
3 0
3
As alluded to in the comments, the issue is with this function:
int sumNumber(Function f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
Let us walk through your code:
Function AA(1,2);
You create a object of type Function, called AA and you allocate each member variable of that object via the constructor (1 and 2).
cout << sumNumber(AA);
You call your method (sumNumber) and pass to it a copy of your variable AA. That function adds the two numbers together and internally calls setSum.
cout << " " << AA.getSum();
You now try to display the sum value by calling the getSum method. But the issue was that you passed a copy of your variable into the sumNumber function. The original AA variable was left alone.
To fix this you need to adjust your function by adding an ampersand &. Like this:
int sumNumber(Function& f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
Now your variable AA is being passed by reference and not by value. There are lots of tutorials about this concept.

C++ RVO: when it happens?

http://coliru.stacked-crooked.com/a/c795a5d2bb91ae32
#include <iostream>
struct X {
X(const char *) { std::cout << 1; }
X(const X &) { std::cout << 2; }
X(X &&) { std::cout << 3; }
};
X f(X a) {
return a;
}
X g(const char * b) {
X c(b);
return c;
}
int main() {
f("hello"); // 13
g("hello"); // 1
}
Is there any difference in the last line of function f(X a):
return a; instead of return std::move(a);?
Is it true that function f doesn't have RVO but g has NRVO?
Is there any difference in the last line of function f(X a): return a; instead of return std::move(a);?
No. a is a local variable of the function, so return a can move from it.
Is it true that function f doesn't have RVO but g has NRVO?
Correct. Named elision never applies to function parameters; it only applies to local variables that are not function parameters.

What does const lambda mean?

#include <iostream>
int foo(int i)
{
const auto a = [&i](){ i = 7; return i * i; };
a();
return i;
}
int main()
{
std::cout << foo(42) << std::endl;
return 0;
}
This compiles( g++ -std=c++11 -Wall -Wextra -Wpedantic main.cpp ) and returns 49. Which is surprising to me, because by declaring a to be a constant object, I would have expected i to be referenced as const int&. It clearly isn't, why?
Lambdas are just like non-lambdas, except their implementation details are hidden. Therefore, it may be easier to explain using a non-lambda functor:
#include <iostream>
int foo(int i)
{
struct F {
int &i;
int operator()() const { i = 7; return i * i; }
};
const F a {i};
a();
return i;
}
int main()
{
std::cout << foo(42) << std::endl;
return 0;
}
F has a int & reference member i. const F cannot have its instance data modified, but a modification to i isn't a modification to its instance data. A modification to its instance data would be re-binding i to another object (which isn't allowed anyway).
[&i](){ i = 7; return i * i; }
is mainly equivalent to
class Lambda
{
public:
Lambda(int& arg_i) : i(arg_i) {}
auto operator() () const { i = 7; return i * i;}
private:
int& i;
};
And so then you have:
const Lambda a(i);
a();
And the const Lambda won't promote its member to const int& i; but int& const i; which is equivalent to int& i;.
When you capure i it is captured as the type it is.
So internally it has a int&. A const before the variable declaration of the closure does not change anything for the lambda.
You have 2 options to solve this:
const int i = 5;
auto b = [&i]() { i++; }; //error on i++
This way a const int& will be captured.
If you cannot change i for some reasons you can do this in c++14
int i = 5;
auto b = [i = static_cast<const int&>(i)]() { i++; }; //error on i++
This casts the int& to a const int& and will be stored as such in the lambda. Though this is way more verbose as you can see.
In the code you gave:
int foo(int i)
{
const auto a = [&i](){ i = 7; return i * i; };
a();
return i;
}
You are not assigning after you initialized your constant lambda function. Therefore, const doesn't mean much in this context.
What you have declared as const it isn't the context of your anonymous function or lambda exspression and its parameters, but only the reference at that lambda expression: const auto a.
Therefore, you cannot change the value of your lambda expr reference a because it is const, but its parameter passed by reference, &i, can be changed within the context of lambda expression.
If I understand correctly, the question is why you're allowed to mutate i even though a is const and presumably contains a reference to i as a member.
The answer is that it's for the same reason that you're allowed to do this on any object - assigning to i doesn't modify the lambda instance, it modifies an object it refers to.
Example:
class A
{
public:
A(int& y) : x(y) {}
void foo(int a) const { x = a; } // But it's const?!
private:
int& x;
};
int main()
{
int e = 0;
const A a(e);
a.foo(99);
std::cout << e << std::endl;
}
This compiles, and prints "99", because foo isn't modifying a member of a, it's modifying e.
(This is slightly confusing, but it helps to think about which objects are being modified and disregard how they're named.)
This "const, but not really" nature of const is a very common source of confusion and annoyance.
This is exactly how pointers behave, where it's more obviously not wrong:
class A
{
public:
A(int* y) : x(y) {}
void foo(int a) const { *x = a; } // Doesn't modify x, only *x (which isn't const).
private:
int* x;
};

Pointer to int. C++

I need to pass to function pointer to int.
Now if I want to pass 5 I'm doing it like this:
int * i = NULL;
int b = 5;
i = &b;
Is there any better way to write it shorter?
I want to pass bytes that are in i int to this function:
void Write2Asm(void* pxAddress, BYTE * MyBytes, int size)
You can just pass &b to the function; no need for an intermediate pointer variable.
Why to create a pointer variable?. Why can't you do it like this?.
int b = 5;
func(&b)
void f(int *i)
{
//...
}
int b = 5;
f(&b);
is enough!
There are a few old C APIs that always take arguments by pointer, even if they're effectively read-only booleans etc.. I'm not recommending it - more for interest's sake - but if you want to go the whole hog you could do something hackish like:
#include <iostream>
struct X
{
X(int n) : n_(n) { std::cout << "X()\n"; }
~X() { std::cout << "~X()\n"; }
operator int&() { return n_; }
operator const int() const { return n_; }
int* operator&() { return &n_; }
const int* operator&() const { return &n_; }
int n_;
};
// for a function that modifies arguments like this you'd typically
// want to use the modified values afterwards, so wouldn't use
// temporaries in the caller, but just to prove this more difficult
// case is also possible and safe...
void f(int* p1, int* p2)
{
std::cout << "> f(&" << *p1 << ", &" << *p2 << ")\n";
*p1 += *p2;
*p2 += *p1;
std::cout << "< f() &" << *p1 << ", &" << *p2 << "\n";
}
int main()
{
// usage...
f(&X(5), &X(7));
std::cout << "post\n";
}
Crucially, the temporaries are valid until after the function call f(...) exits.

What is ->* operator in C++?

C++ continues to surprise me.
Today i found out about the ->* operator. It is overloadable but i have no idea how to invoke it. I manage to overload it in my class but i have no clue how to call it.
struct B { int a; };
struct A
{
typedef int (A::*a_func)(void);
B *p;
int a,b,c;
A() { a=0; }
A(int bb) { b=b; c=b; }
int operator + (int a) { return 2; }
int operator ->* (a_func a) { return 99; }
int operator ->* (int a) { return 94; }
int operator * (int a) { return 2; }
B* operator -> () { return p; }
int ff() { return 4; }
};
void main()
{
A a;
A*p = &a;
a + 2;
}
edit:
Thanks to the answer. To call the overloaded function i write
void main()
{
A a;
A*p = &a;
a + 2;
a->a;
A::a_func f = &A::ff;
(&a->*f)();
(a->*f); //this
}
Just like .*, ->* is used with pointers to members. There's an entire section on C++ FAQ LITE dedicated to pointers-to-members.
#include <iostream>
struct foo {
void bar(void) { std::cout << "foo::bar" << std::endl; }
void baz(void) { std::cout << "foo::baz" << std::endl; }
};
int main(void) {
foo *obj = new foo;
void (foo::*ptr)(void);
ptr = &foo::bar;
(obj->*ptr)();
ptr = &foo::baz;
(obj->*ptr)();
return 0;
}
The overloaded ->* operator is a binary operator (while .* is not overloadable). It is interpreted as an ordinary binary operator, so in you original case in order to call that operator you have to do something like
A a;
B* p = a->*2; // calls A::operator->*(int)
What you read in the Piotr's answer applies to the built-in operators, not to your overloaded one. What you call in your added example is also the built-in operator, not your overloaded one. In order to call the overloaded operator you have to do what I do in my example above.
Like any other opperator, you can also call it explicitly:
a.operator->*(2);