//: C12:OverloadingUnaryOperators.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt

#include <iostream>
using namespace std;

/* Non-member functions: */

/*In questa classe vengono definite della member function di tipo "friend" che implementano degli operatori che possono essere chiamati come funzioni esterna alla classe. Per esempio l'operatore "+" posso richiamarlo senza 'agganciarlo' ad un oggetto. Es: a.+ (sintassi errata); +a (sintassi esatta);*/


class Integer
{

long i;
Integer* This() { return this; }

public:

Integer(long ll = 0) : i(ll) {}
/* No side effects takes const& argument: */
friend const Integer& operator+(const Integer& a);
friend const Integer operator-(const Integer& a);
friend const Integer operator~(const Integer& a);
friend Integer* operator&(Integer& a);
friend int operator!(const Integer& a);

/* Side effects have non-const& argument: */
/* Prefix: */

friend const Integer& operator++(Integer& a);
/* Postfix: */
friend const Integer operator++(Integer& a, int);
/* Prefix: */
friend const Integer& operator--(Integer& a);
/* Postfix: */
friend const Integer operator--(Integer& a, int);

};

/* Global operators: */

/*Di seguita vengono definiti i vari operatori.*/
const Integer& operator+(const Integer& a)
{

cout << "+Integer\n";
return a; // Unary + has no effect

}

const Integer operator-(const Integer& a)
{

cout << "-Integer\n";
return Integer(-a.i);

}

const Integer operator~(const Integer& a)
{

cout << "~Integer\n";
return Integer(~a.i);

}

Integer* operator&(Integer& a)
{

cout << "&Integer\n";
return a.This(); // &a is recursive!

}

int operator!(const Integer& a)
{

cout << "!Integer\n";
return !a.i;

}

/* Prefix; return incremented value */
const Integer& operator++(Integer& a)
{

cout << "++Integer\n";
a.i++;
return a;

}

/* Postfix; return the value before increment: */
const Integer operator++(Integer& a, int)
{

cout << "Integer++\n";
Integer before(a.i);
a.i++;
return before;

}

/* Prefix; return decremented value */
const Integer& operator--(Integer& a)
{

cout << "--Integer\n";
a.i--;
return a;

}

/* Postfix; return the value before decrement: */
const Integer operator--(Integer& a, int)
{

cout << "Integer--\n";
Integer before(a.i);
a.i--;
return before;

}

/* Show that the overloaded operators work: */
void f(Integer a)
{

+a;
-a;
~a;
Integer* ip = &a;
!a;
++a;
a++;
--a;
a--;

}

/* Member functions (implicit "this"): */
class Byte
{

unsigned char b;

public:

Byte(unsigned char bb = 0) : b(bb) {}
/* No side effects: const member function: */
const Byte& operator+() const
{

cout << "+Byte\n";
return *this;

}
const Byte operator-() const
{

cout << "-Byte\n";
return Byte(-b);

}
const Byte operator~() const
{

cout << "~Byte\n";
return Byte(~b);

}
Byte operator!() const
{

cout << "!Byte\n";
return Byte(!b);

}
Byte* operator&()
{

cout << "&Byte\n";
return this;

}

/* Side effects: non-const member function: */
const Byte& operator++()
{

/* Prefix */
cout << "++Byte\n";
b++;
return *this;

}

const Byte operator++(int)
{

/* Postfix */
cout << "Byte++\n";
Byte before(b);
b++;
return before;

}

const Byte& operator--()
{

/* Prefix */
cout << "--Byte\n";
--b;
return *this;

}

const Byte operator--(int)
{

/* Postfix */
cout << "Byte--\n";
Byte before(b);
--b;
return before;

}

};

void g(Byte b)
{

+b;
-b;
~b;
Byte* bp = &b;
!b;
++b;
b++;
--b;
b--;

}

int main()
{

Integer a;
f(a);
Byte b;
g(b);

} ///:~