
//
// To jest przykładowy kod z podrozdziału 9.7.1 „Typy argumentów” książki 
// "Programowanie. Teoria i praktyka z wykorzystaniem C++" Bjarne'a Stroustrupa.
//

#include <iostream>

using namespace std;

//------------------------------------------------------------------------------

class Year {        // Rok mieści się w zakresie [min:max).
    static const int min = 1800;
    static const int max = 2200;
public:
    class Invalid { };
    Year(int x) : y(x) { if (x<min || max<=x) throw Invalid(); }
    int year() { return y; }
private:
    int y;
};

//------------------------------------------------------------------------------

class Date {
public:
    enum Month {
        jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
    };

    Date(Year yy, Month mm, int dd) : y(yy), m(mm), d(dd) // Sprawdza poprawność daty i wykonuje inicjację.
    {
        // ...
    }

    // ...
private:
    Year y;
    Month m;
    int d;   // dzień
};

//------------------------------------------------------------------------------

int main()
try
{
    //Date dx1(Year(1998), 4, 3);         // Błąd: drugi argument nie jest typu Month.
    //Date dx2(Year(1998), 4, Date::mar); // Błąd: drugi argument nie jest typu Month.
    //Date dx2(4, Date::mar, Year(1998)); // Błąd: pierwszy argument nie jest typu Year.
    //Date dx2(Date::mar, 4, Year(1998)); // Błąd: drugi argument nie jest typu Month.
    Date dx3(Year(1998), Date::mar, 30);  // ok

    // Ten dziwny i mało prawdopodobny błąd nie zostałby znaleziony do czasu uruchomienia programu:
    Date dx5(Year(4), Date::mar, 1998);   // Błąd czasu wykonywania: Year::Invalid
}
catch (Year::Invalid&) {
    cerr << "Błąd: nieprawidłowy rok.\n"; 
    return 1;
}
catch (...) {
    cerr << "Nieznany wyjątek!\n"; 
    return 2;
}

//------------------------------------------------------------------------------
