This is another example extracted from B.Stroustrup's new book "TCPL", more specifically from itsSection 16.3 Concrete Classes. As this is a rather long section, I'll summarize the points of interest below.
namespace Chrono { enum class Month { jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec }; class Date { public: class Bad_date { }; explicit Date(int dd ={}, Month mm ={}, int yy ={}); int day() const; Month month() const; int year() const; Date& add_year(int n); Date& add_month(int n); Date& add_day(int n); private: bool is_valid(); int d, m, y; }; bool is_date(int d, Month m, int y); bool is_leapyear(int y); bool operator==(const Date& a, const Date& b); bool operator!=(const Date& a, const Date& b); const Date& default_date(); ostream& operator<<(ostream& os, const Date& d); istream& operator>>(istream& is, Date& d); } // Chrono
Constructor definition:
Date::Date(int dd, Month mm, int yy) :d{dd}, m{mm}, y{yy} { if (y == 0) y = default_date().year(); if (m == Month{}) m = default_date().month(); if (d == 0) d = default_date().day(); if (!is_valid()) throw Bad_date(); }
Helper function default_date() definition:
const Date& Chrono::default_date() { static Date d {1,Month::jan,1970}; return d; }If this function is thread safe, as I expected it to be (from §6.7/4), then what is the purpose of std::call_once()?