# 5779 b and 5778

## 5779-moed-b

### Question 1

```cpp
#include <iostream>
using namespace std;

class Base {
public:
    Base(){}
    void Print( ){
        cout <<" I am base "<<endl;
    }

    Base& operator=(const Base & b){
        return this;
    }
};

class Derived : public Base {
public:
    Derived():Base(){}

    void Print( ){
        cout <<" I am derived "<<endl;
    }
    Derived& operator=(const Derived &){
        return this;
    }
};

int main() {
    Derived d;
    Base b;
    b=d;
    b.Print();
    return 0;
}
```

#### Part a

There are **2** compile time error, what are they and how can we fix them?

#### Solution

**1st error**

Here

```cpp
Base& operator=(const Base & b){
        return this;
    }
```

and here, we should return a **reference** but returned a **pointer**

```cpp
Derived& operator=(const Derived &){
        return this;
    }
```

**Fix**: `this` instead of `*this` (asterisk this)

* `this`  is pointer, that is why we see code like `this->x`
* `*this` is the reference

**Part b**

What will be the output after the fix?

**Solution**

```
I am base
```

Explanation: **Object slicing** [more info](https://www.geeksforgeeks.org/object-slicing-in-c/)

```cpp
Derived d;
Base b;
b=d;
```

**Part c**

Lets now **only** change our **main** to this

```cpp
#include <iostream>
using namespace std;

class Base {
public:
    Base(){}
    void Print( ){
        cout <<" I am base "<<endl;
    }

    Base& operator=(const Base & b){
        return this;
    }
};

class Derived : public Base {
public:
    Derived():Base(){}

    void Print( ){
        cout <<" I am derived "<<endl;
    }
    Derived& operator=(const Derived &){
        return this;
    }
};

int main() {
     Derived d;
     Base b;
     b=d;
     b.Print();
     d=b;
     d.Print();
     return 0;
}
```

In the code there is **1** compile-time error, , what is and how can it be fixed **without changing the main**?

**Solution**

```cpp
class Derived : public Base {
public:
    Derived():Base(){}
    ...
    Derived& operator=(const Derived &){
        return *this;
    }
};

int main() {
     Derived d;
     Base b;
     b=d;
     b.Print();
     d=b;       // < ==== here we try to convert from Based to Derived
     d.Print();
     return 0;
}
```

`d=b` tries to convert from **Based** to **Derived** to type but the `=` operator receives a **Derived** type.

In C++, a derived class object can be assigned to a base class object, but the other way is not possible.

> Tip: remember we call the `=` operator since **b** has already been created

**Fix:**

```cpp
Derived& operator=(const Base &){
        return *this;
    }
```

**Part d**

What is the output?

**Solution**

```
 I am base 
 I am derived
```

Remember `=` operator didn't really do anything and return `*this`

### Question 2:

```cpp
#include <iostream>
#include <string>
using namespace std;

class Player {
public:
    void play() {
        cout << "Error: Player.play is not defined" << endl;
    }
};

class SmartPlayer: public Player {
public:
    void play() {
        cout << "Smart Move" << endl;
    }
};

class SimplePlayer: public Player {
public:
    void play() {
        cout << "Simple Move" << endl;
    }
};

void game(Player* player1, Player* player2, int turns) {
    for (int i=0; i<turns; ++i) {
        player1->play();
        player2->play();
    }
}

int main() { // a demo program
    game(new SmartPlayer(), new SimplePlayer(), 5);
}
```

We get the following 10 times

```
Error: Player.play is not defined
```

Why type of error is this:

* compilation
* linker
* runtime
* logic
* memory leak

Additionally, what caused the error?

**Solution**

logic

```cpp
class Player {
public:
    void play() {        // < ========= Should be virtual
        cout << "Error: Player.play is not defined" << endl;
    }
};

class SmartPlayer: public Player {
public:
    void play() {...}
};
```

Since `Player::play` **isn't** `virtual` we call`Player::play` instead of `SmartPlayer::play`

#### Part b:

**Fix**: add `virtual`

```cpp
class Player {
public:
    virtual void play() {
        cout << "Error: Player.play is not defined" << endl;
    }
};
```

#### Part c:

What is the output now?

```
Smart Move
Simple Move
Smart Move
Simple Move
Smart Move
Simple Move
Smart Move
Simple Move
Smart Move
Simple Move
```

#### Question 3

```cpp
#include <iostream>
using namespace std;

void change(int*& ip, int j) {
    ip = (int *)(++j);
}

int main() {
    int* ip = 0,j=0;
    change(ip,j);
    cout << "ip = " << ip << " j="<< (j++) <<endl;
    cout << "ip = " << (++ip) << " j="<< j <<endl;
    return 0;
}
```

#### Part A:

Is there a compilation **or** any other type or error? If so, explain the error.

#### Solution

* There is no compilation error
* There is a warning
* ```
  main.cpp:5:10: warning: cast to 'int *' from smaller integer type 'int' [-Wint-to-pointer-cast]
      ip = (int *)(++j);
  ```

The compiler is warning us that usually we increment by 4 bytes lets say `++ip` but here it can be something else and we may be leaving the memory space we wanted.

**Part b**

```
ip = 0x1 j=0
ip = 0x5 j=1
```

* Remember `ip = (int *)(++j);` that here **ip** incremented by 1 and `ip = 0x1`
* Then `(++ip)` will increment by the size of an **int** which is **4 bytes** to the next address.

#### Question 4:

```cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct Person {
    string name;
    int age;
};

int main() {
    vector<Person> unsorted { {"bbb",11}, {"aaa",33}, {"ddd",22}, {"ccc",44} };
    vector<Person> sorted_by_age = unsorted;
    sort(sorted_by_age.begin(), sorted_by_age.end());

    for (Person p: sorted_by_age)
        cout << p.age << " ";
}
```

output:

```
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/bits/predefined_ops.h:43:23: error:
invalid
 operands to binary expression ('Person' and 'Person')
 { return *__it1 < *_
   ~~~~~~ ^ ~~~~~~

...

question.cpp:14:8: note: in instantiation of function template specialization
 'std::sort<__gnu_cxx::__normal_iterator<Person *, std::vector<Person,
std::allocator<Person> > > >' requested here
 sort(sorted_by_age.begin(), sorted_by_age.end());
 ^
```

* What type of error is this?
* Why does the error point to a file that we didn't write
* Why after the error-message there is a **note** that points to code that we did write?

  **Solution**

**Compilation error**

* `std::sort` compares between objects using `>` operator
* We didn't implement a `>` operator for `Person`&#x20;
* Usually **template instantiations** are created on compile time. Usually template error are very long

#### Part b

Add **before** the **main** function code so that **sorted\_by\_age** will contain the people sorted by **age** (youngest to oldest)

**Solution 1: adding to global scope**

```cpp
bool operator<(Person a,Person b) {
    return a.age < b.age;
}
```

**Solution 2: adding to Person**

```cpp
struct Person {
    string name;
    int age;

    bool operator<(Person b) {
        return age < b.age;
    }
};
```

#### Part C

```cpp
sort(sorted_by_age.begin(), sorted_by_age.end());
```

add here so that **sorted\_by\_age** will contain the people sorted by **age** (youngest to oldest)

**Solution**

We will add a lambda function as so: `[](Person a, Person b){return a.age<b.age;}`

```cpp
sort(sorted_by_age.begin(), sorted_by_age.end(), [](Person a, Person b){return a.age<b.age;});
```

or like this

```cpp
[](const Person& a, const Person& b){return a.age<b.age;});
```

or this

```cpp
[](auto a, auto b){return a.age<b.age;});
```

#### Question 7: (22 pts)

Write a class **binop** that its ctor receives **3 parameters**

* 2 container (iterables) with the same length
* **Binary** functor (or lambda)

The `binop` returns a container (iterable) from the binary function on both containers.

for example:

```cpp
vector<int> v1 {10,  20,  30,  40,  50};
list<double> L1{1.1, 2.2, 3.3, 4.4, 5.5};
auto vl = binop(v1, L1, [](int x,double y){return x+y;});
        //vl =  11.1 22.2 33.3 44.4 55.5
```

> Note: If the lengths are different the result is undefined

```cpp
#include <iostream>
#include <vector>
#include <list>
using namespace std;
#include "range.hpp"
#include "binop.hpp"
using namespace itertools;

int main() {
    vector<int> v1{10,20,30,40,50};
    list<double> L1{1.1, 2.2, 3.3, 4.4, 5.5};

    for (auto i: binop(v1, L1, [](int x,double y){return x+y;} ))
        cout << i << " "; // Prints 11.1 22.2 33.3 44.4 55.5
    // since 11.1 = 10 + 1.1, 22.2 = 20 + 2.2, etc.
    cout << endl;

    for (auto i: binop(v1, range(1,6), [](int x,int y){return x*y;} ))
        cout << i << " "; // Prints 10 40 90 160 250
    // since 10*1 = 10, 20*2 = 40, etc.
    cout << endl;

    return 0;
}
```

Here is the beginning of `binop.hpp`

```cpp
namespace itertools {
     template<typename T1, typename T2, typename OP>
     class binop {
     ...
     };
}
```

* Assume that `range.hpp` is already written correctly
* **Only finish** `binop.hpp`

#### Possible Solution

Lets remember how a for loop looks with an iterator

```cpp
for (vector<int>::iterator it=v.begin(); it!=v.end(); ++it)
        cout << ' ' << *it;
```

Things we must implement

* ctor
* iterator
* `operator*`
* `operator++`
* `operator==`
* `operator!=`
* `begin()`
* `end()`

```cpp
namespace itertools {
    template<typename T1, typename T2, typename OP>
    class binop {
    public:
        const T1 first;
        const T2 second;
        const OP op;

        binop(const T1 &first, const T2 &second, OP op) : first(first), second(second), op(op) {}

        struct iterator {
            decltype(first.begin()) firstIterator, firstEnd;
            decltype(second.begin()) secondIterator, secondEnd;
            const OP op;

            auto operator*() {
                return op(*firstIterator, *secondIterator);  //rember we have to dereference and send the values
            }

            iterator &operator++() { //prefix ++v
                ++firstIterator;
                ++secondIterator;
                return *this;
            }

            iterator operator++(int) { //postfix v++
                iterator tmp = *this;
                operator++();
                return tmp;
            }

            bool operator==(const iterator &other) {
                return firstIterator == other.firstIterator && secondIterator == other.secondIterator;
            }

            bool operator!=(const iterator &other) {
                return !(operator==(other));
            }
        };

        iterator begin() const {
            return iterator{first.begin(), first.end(), second.begin(), second.end(), op};
        }

        iterator end() const {
            return iterator{first.end(), first.end(), second.end(), second.end(), op};
        }
    };
}
```

## 5778 moed-a

```cpp
#include <iostream>
using namespace std;

class triplet {
    double x,y,z;
public:
    triplet(double x, double y,double z): x(x), y(y), z(z) {}
    friend ostream& operator<< (ostream& out, const triplet& t);
};

ostream& operator<< (ostream& out, const triplet& t) {
    out << "(" << t.x << "," << t.y << "," << t.z << ")";
}

int main() {
    triplet t(1,2,3);
    cout << t << endl;
}
```

Why type of error is this:

* compilation
* linker
* runtime
* logic
* memory leak

Additionally, what caused the error?

#### Solution

**runtime** error

```cpp
ostream& operator<< (ostream& out, const triplet& t) {
    out << "(" << t.x << "," << t.y << "," << t.z << ")"; // < ===== no return
}
```

Now the operator will return garbage- or basically an invalid reference

```cpp
int main() {
    triplet t(1,2,3);
    cout << t << endl; // <===== here
}
```

`cout << t` returns garbage, then `<< endl` will try to write to an **invalid address** throwing an exception

#### Part b

fix the code by adding **1** line of code

#### Solution

```cpp
ostream& operator<< (ostream& out, const triplet& t) {
    out << "(" << t.x << "," << t.y << "," << t.z << ")";
    return out;
}
```

#### Question 2:

```cpp
#include <iostream>
using namespace std;

class LargeMatrix {
public: // ...
    LargeMatrix(int width, int height) {
        cout << "standard ctor" << endl; // ...
    }
    LargeMatrix(const LargeMatrix& other) {
        cout << "copy ctor" << endl; // ...
    }
};

int sum_of_values(LargeMatrix m) {
    cout << "sum_of_values" << endl;
    int result = 0;
    // do calculation ...
    return result;
}

int main() {
    LargeMatrix m1(1000,1000);
    // ...
    cout << sum_of_values(m1) << endl;
}
```

```
standard ctor
copy ctor
sum_of_values
0
```

The code **works** but runs **slow**, what is the bug?

#### Solution

```cpp
int sum_of_values(LargeMatrix m) {
    ...
}
```

* Here `m` is passed by **value**
* So the **copy ctor** is called
* The copy ctor will copy **1,000,000** values which takes time

to fix this we just pass by reference `&`

```cpp
int sum_of_values(LargeMatrix& m) {
    ...
}
```
