conditional operator can return reference? - c++

I came across a line of code and never thought it might work well. I thought the conditional operator return value and does not work with reference.
Some pseudo code:
#include <iostream>
using namespace std;
class A {
public:
A(int input) : v(input) {};
void print() const { cout << "print: " << v << " # " << this << endl; }
int v;
private:
//A A(const A&);
//A operator=(const A&);
};
class C {
public:
C(int in1, int in2): a(in1), b(in2) {}
const A& getA() { return a;}
const A& getB() { return b;}
A a;
A b;
};
int main() {
bool test = false;
C c(1,2);
cout << "A # " << &(c.getA()) << endl;
cout << "B # " << &(c.getB()) << endl;
(test ? c.getA() : c.getB()).print(); // its working
}
Can someone explain? Thx.

Your assumption about the conditional operator is wrong. The type of the expression is whatever type the expressions c.getA() and c.getB() have, if they have the same type, and if they denote lvalues, then so does the entire expression. (The exact rules are in §5.16 of the C++ standard.)
You can even do this:
(condition? a: b) = value;
to conditionally set either a or b to value. Note that this is C++-specific; in C, the conditional operator does not denote an lvalue.

Related

Convert int to class pointer?

I am trying to create a cast from A* to int where A is a class I've defined.
The conversion is from a lookup, (the int is the id of that A instance) in case you wanted to know.
Currently, I have:
#include <iostream>
class A{
private:
int val;
public:
A(){};
A(int val): val(val){};
static A* cast(int val){
return &(A());
//This will actually be a valid pointer
}
explicit operator int(){
return val;
}
};
int main() {
A a(7);
std::cout << "Pointer: " << &a << std::endl;
std::cout << "Pointer cast: " << A::cast(5) << std::endl; //would like this to be static_cast<A*>(5)
std::cout << "Int cast: " << static_cast<int>(a) << std::endl;
}
I can create a nice cast from A to int. However, I cannot figure out how to define the casts for A* to int and vice versa.
Note: I currently have this working as a function in the A class, but a cast-style conversion would feel more natural in my use case.

Why ambiguity only for overloaded operators and not for functions with "same" name but different scope?

Consider the example:
class Gfg {
public:
void printHello()
{
cout << "hello gfg-class specific" << endl;
}
};
void printHello()
{
cout << "hello gfg-global" << endl;
}
int main()
{
Gfg a;
a.printHello();
printHello();
}
This code works fine.
But see other example for operator overloading, it will not compile.
class Gfg {
public:
Gfg operator+(Gfg& a)
{
cout << "class specific + operator" << endl;
return Gfg(); // Just return some temporary object
}
};
Gfg operator+(Gfg& a, Gfg& b)
{
cout << "global + operator called" << endl;
return Gfg(); // Just return some temporary object
}
int main()
{
Gfg a, b;
Gfg c = a + b;
}
I thought in both cases name mangling(decoration) will make both name as unique name and member function will be given preference and hence member version of operator+ should be called, which doesn't happen. why?
The ambiguity resides in the use of c = a+b;. It is ambiguous because we do not know if we call the operator in the class (with one parameter) or the one outside the class (with two parameters). Using the call with the operator keyword clarifies a little bit: c=a.operator+(b) or c =operator+(a,b).
Thus the ambiguity.
I modified your code like this:
#include <iostream>
using namespace std;
class Gfg {
public:
Gfg operator+(const Gfg& a)
{
cout << "class specific + operator" << endl;
return Gfg(); // Just return some temporary object
}
};
Gfg operator+(const Gfg& a, const Gfg& b)
{
cout << "global + operator called" << endl;
return Gfg(); // Just return some temporary object
}
int main()
{
Gfg a, b,c,d;
c = operator+(a,b); // equivalent to c = a+b
c = a.operator+(b); // also equivalent to c=a+b
}
The code compiles and the output is the following :
global + operator called
class specific + operator

How to pass an unrelated class in a constructor of another class?

Extra line of code can be added only to the place where '>>' sign is present.
My targeted input and output is as follows:
Input: 15
Output : 16:15:17:16:
I need help only in
cout << r.get() << ":";
part. An explanation would be helpful.
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int ai) : i(ai) {}
int get() const { return i; }
void update() { ++i; }
};
class B {
int i;
public:
B(int ai) : i(ai) {}
int get() const { return i; }
//>>
operator A() {return A(i);}
void update() { ++i; }
}; // End of class B
int main() {
int i;
cin >> i;
A a(i++);
B b(i);
const B &r = static_cast<B>(a);
a.update();
cout << a.get() << ":";
cout << r.get() << ":";
const A &s = static_cast<A>(b);
b.update();
cout << b.get() << ":";
cout << s.get() << ":";
return 0;
}
You cannot solve the asker's problem by modifying a conversion operator in class B. B's conversion operators only tell the constructor how to make another datatype out of a B. To do this with a conversion operator, the operator needs to be in class A.
class B; // forward declaration of B so that A knows it exists
class A
{
int i;
public:
A(int ai) :
i(ai)
{
}
int get() const
{
return i;
}
void update()
{
++i;
}
operator B(); // cannot implement the function yet because we do not have a
// complete definition of B. Without a definition of B we cannot
// construct B excluding forward defined helper functions that are
// implemented later, gaining us nothing.
};
Then later after B is fully defined,
A::operator B()
{
return B(i); // now we have enough information to construct a B
}
Note: We can reduce some of this messiness by moving the definition of B to before the definition of A. Unfortunately this makes the code required to support the
const A &s = static_cast<A>(b);
that comes later in the code require forward declaration of A and the implementation of the B to A conversion operator outside the definition of B.
An alternative is adding a constructor to B that takes an A
B::B(const A& a): i(a.get())
{
}
and vice-versa for A.

Why I can use the class name as a function name?

As far as I know in C++ we cannot use the same identifier for another declaration:
int x;
char x; // compile-time error: redefinition.
But here is an example where I was messing with classes:
#include "stdafx.h"
#include <iostream>
#include <vector>
class A {
public:
A(int);
void print()const;
friend std::ostream& operator << (std::ostream& out, A& rhs);
private:
int value1;
};
std::ostream& operator << (std::ostream& out, A& rhs) {
out << "rhs.value1 = " << rhs.value1 << std::endl;
return out;
}
A::A(int x) : value1(x) { std::cout << "ctor A(x)" << std::endl; }
void A::print()const {
std::cout << "value1: " << value1 << std::endl;
}
int A(int x) {
std::cout << "inside A(int x)" << std::endl;
return x;
}
int main(){
class A a { 0 };
a = A(7);
a.print();
std::cout << A(7) << std::endl;
std::cout << A(5) << std::endl; // here if I comment out the function a it is ok as long as I overloaded the insertion operator
// and if I add the function A it hides the insertion operator!
std::cout << std::endl;
std::cin.get();
return 0;
}
So as you can see above I must add the keyword class whenever I declare an object of class Aotherwise I get a compile-time error. Why?
Is the expression a = A(7); a function call and the return value is passed to the constructor of class A that takes an integer. Or simply no function call but only ctor call?
From my point of view, you have a class A and a function A, so you have to point out A is a class or a function that's why you have to add "class" when you declare an object of A.
According to the following code, two classes, A and B, are defined, they are exactly same, but A can be a function or a class, so when you declare a object A, you have to add a "class" before A, while declare a object of B is no need to add a "class"
For the second question, first function A is called, and its return value is used to construct object a. You can see first x=7 is in the function A, and ctor x=8 because the function return x+1.
The output:
ctor A(x) x=0
inside A(int x) x=7
ctor A(x) x=8
ctor B(x)
The test code:
#include <iostream>
#include <vector>
class A {
public:
A(int);
private:
int value1;
};
class B {
public:
B(int);
private:
int value1;
};
B::B(int x) : value1(x) { std::cout << "ctor B(x)" << std::endl; }
A::A(int x) : value1(x) { std::cout << "ctor A(x) x=" << x <<std::endl; }
int A(int x) {
std::cout << "inside A(int x) x=" << x << std::endl;
x=x+1;
return x;
}
int main(){
class A a(0);
a = A(7);
B b(0);
return 0;
}

Polymorphism does not work with pointers, operator<< overload, inheritance, C++

I have a problem with my code. I have two classes, A and B, and B inherits A. I also have operators << overloaded in both classes.
Everything works, I have no compiler errors, but it seems something is wrong. As far as I understand polymorphism, when I use pointers to base class while creating child class with new, calling a method should match the child class, not the base class.
For the code below,
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
A(int aa) : a(aa) {};
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
private:
int b;
public:
B(int bb, int aa) : A(aa), b(bb){}
int getb() const {return b;}
};
ostream & operator << ( ostream & os, const B & o)
{
os << static_cast <const A &>(o);
os << "\n";
os << "b = " << o.getb() << "\n";
return os;
}
int main()
{
A *o1 = new B(2,3);
cout << *o1;
cout << "---------------------\n";
B *o2 = new B(2,3);
cout << *o2;
return 0;
}
In main:
A *o1 = new B(2,3);
cout << *o1;
Shows a = 3, instead of showing a = 3 b = 2 (the call should match the child class, not the base class). The thing is, I need to implement the << and >> operators in every child class, but I think they do not behave as they should.
The output of the program:
Even the modified code with re-implmented show method shows wrong results, it does not show a at all this time:
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
A(int aa) : a(aa) {};
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
private:
int b;
public:
B(int bb, int aa) : A(aa), b(bb) {}
int getb() const
{
return b;
}
void show(ostream& o) const
{
o << "b = " << b << "\n";
}
};
ostream & operator << ( ostream & os, const B & o)
{
os << static_cast <const A &>(o);
o.show(os);
return os;
}
int main()
{
A *o1 = new B(2,3);
cout << *o1;
cout << "---------------------\n";
B *o2 = new B(2,3);
cout << *o2;
return 0;
}
enter image description here
you have to implement the virtual function show in derived class B:
class B: public A
{
public:
// some code here
virtual void show(ostream& o) const
{
o << "b = " << b << "\n";
}
};
when I use pointers to base class while creating child class with new,
calling a method should match the child class, not the base class
It does when you call a member function ("method" in some other languages), but operator<< is not a member function – it's an overloaded free function.
When choosing an overload, only the types known at compile-time are used.
Since o1 is an A*, *o1 is an A&, and the overload for A& is chosen.
You're doing this a bit "backwards"; you only need one operator<<, for the base class, which calls the virtual show, and then you override show in the derived classes.
Like this:
class A
{
// ...
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
// ...
void show(ostream& o) const override
{
A::show(o); // Do the "A part".
o << "b = " << b << "\n";
}
};
Follow the same pattern for operator>>.