// Code derived from Stroustrup's PPP2 book
// § 9.7.1 Argument types
// -and beginning on p 325
#include <iostream>
using namespace std;
// year in [min:max) range
class Year {
static const int min = 1800;
static const int max = 2200;
public:
Year(int x) : y{x}
{
if (x < min || max <= x)
throw Invalid{};
}
class Invalid {};
int year() { return y; }
private:
int y;
};
enum class Month {
jan = 1,
feb,
mar,
apr,
may,
jun,
jul,
aug,
sep,
oct,
nov,
dec
};
class Date {
public:
Date(Year y, Month m, int d);
// . . .
Year year() { return y; }
Month month() { return m; }
int day() { return d; }
private:
Year y;
Month m;
int d; // day
};
Date::Date(Year yy, Month mm, int dd) : y{yy}, m{mm}, d{dd} {}
int main()
try {
// Date dx1{Year{1998}, 4, 3}; // error: 2nd argument not a Month
// Date dx2{Year{1998}, 4, Month::mar}; // error: 2nd argument not a Month
// Date dx2{4, Month::mar, Year{1998}}; // error: 1st argument not a Year
// Date dx2{Month::mar, 4, Year{1998}}; // error: 2nd argument not a Month
Date dx3{Year{1998}, Month::mar, 30}; // OK
// This unlikely error would still not be caught until run-time:
Date dx2{Year{4}, Month::mar, 1998}; // run-time error: Year::Invalid
} catch (Year::Invalid&) {
cerr << "error: Invalid year\n";
return 1;
} catch (...) {
cerr << "Oops: unknown exception!\n";
return 2;
}