//
//  fun with reference parameters
//

#include <iostream>

// a normal function
int foo1(int x) {
return x*4;
}

// an unsuccessful attempt to return a value through a parameter
void foo2(int x) {
x = x*4;
}

// reference parameters allow us to change the value of something
// passed to us. But the "normal function" approach is preferred.
void foo3(int &x) {
x = x*4;
}

// We can use reference parameters to get more than one value back
// to the caller. There are other ways to solve this problem, but
// this approach is use. Probably not great if you are trying to
// get 23 values back. More on that latter.
void return_more_than_one_thing(int in1, int in2, int &out1, int &out2) {
out1 = in1 - in2;
out2 = in2 - in1;
}

// a tempting problem to use references for
void swap(int &one_place, int &another_place) {
int temp;
temp = one_place;
one_place = another_place;
another_place = temp;
}

// another use of references is to return values and to use
// the return only for returning the status of the operation.
int divide(double dividend, double divisor, double &quotient) {
if (divisor == 0){
return 0;
}
quotient = dividend/divisor;
return 1;
}

using namespace std;

int main() {
cout << "trying function foo1 " << foo1(42) << endl << endl;

int x = 42;
cout << "x before function foo2 " << x << endl;
foo2(x);
cout << "x after function foo2 " << x << endl <<endl;

cout << "x before function foo3 " << x << endl;
foo3(x);
cout << "x after function foo3 " << x << endl <<endl;

// this will not work:
// foo3(14);

int y = 12;
int normal_difference = 98;
int reverse_difference = 99;
cout << "Before function return_more_than_one_thing " << x << " " << y << " " << normal_difference << " " << reverse_difference << endl;
return_more_than_one_thing(y, 14, normal_difference, reverse_difference);
cout << "After function return_more_than_one_thing " << x << " " << y << " " << normal_difference << " " << reverse_difference << endl << endl;

cout << "Before function swap " << x << " " << y <<  endl;
swap(x, y);
cout << "After function swap " << x << " " << y << endl << endl;

// safe division
double quotient = 31.6;
cout << "Trying to divide 23 by 45\n";
if (divide(23,45,quotient)) {
cout << "All is well, division operation is valid and yields: "  << quotient << endl;
}
else {
cout << "You can not divide by 0, no valid quotient.\n";
}
cout << endl;

cout << "Trying to divide 23 by 0\n";
if (divide(23,0,quotient)) {
cout << "All is well, division operation is valid and yields: "  << quotient << endl;
}
else {
cout << "You can not divide by 0, no valid quotient.\n";
}

char ch;
cin >> ch;
return 0;
} 