C++ Locales by Nathan Myers Listing One #include // istream, ostream #include // struct tm namespace ChronLib { class Date { long day; // days since 1752-09-14 public: enum Month { jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec }; Date(int year, Month month, int day); void asCLibTime(struct tm*) const; }; std::ostream& operator<< (std::ostream& os, Date const& date); std::istream& operator>> (std::istream& is, Date& date); } Listing Two namespace std { template Facet const& use_facet(locale const& loc); }; Listing Three // date_insert.C #include // struct tm #include // ostream #include // use_facet #include "date.h" std::ostream& ChronLib::operator<<(std::ostream& os, Date const& date) { using namespace std; ostream::sentry cerberus(os); if (!cerberus) return os; struct tm tmbuf; date.asCLibTime(&tmbuf); use_facet< time_put >(os.getloc()) .put(os, os, os.fill(), &tmbuf, 'x'); return os; } Listing Four #include // cout #include // locale #include "date.h" int main() { using namespace std; using ChronLib::Date; cout.imbue(locale("")); cout << Date(1942, Date::dec, 7) << endl; return 0; } Listing Five //stats.h #include class Stats : public std::locale::facet { public: static std::locale::id id; Stats (int ss) : shoeSize_(ss) {} int shoeSize() const { return shoeSize_; } private: Stats (Stats&); // not defined: void operator=(Stats&); // not defined: int shoesize_; }; //stats.C #include "stats.h" std::locale::id Stats::id; Listing Six locale here(locale(), new Stats(48)); int ss = use_facet(here).shoesize(); Listing Seven class locale { public: class facet; class id; ~locale() { if (imp_->refs_-- == 0) delete imp_; } locale() : imp_(__global_imp) { ++imp_->refs; } explicit locale(char const* name); locale(locale const& other) : imp_(other.imp_) { ++imp_->refs_; } locale& operator=(locale const& l); template locale(locale const& other, Facet* f); // other constructors template friend Facet const& use_facet(locale const&); private: struct imp { size_t refs_; // ref-counter vector facets_; ~imp(); imp(imp const&); }; imp* imp_; }; Listing Eight class locale::facet { friend class locale; friend class locale::imp; size_t refs_; //initially 0 = One reference protected: explicit facet(int refs = 0); virtual ~facet(); }; Listing Nine class locale::id { friend class locale; size_t index_; static size_t mark_; }; Listing Ten template locale::locale(locale const& other, Facet* f) { imp_ = new imp(*other.imp_); imp_->refs_ = 0; // one reference size_t& index = Facet::id.index_; if (!index) index = ++Facet::id.mark_; if (index >= imp_->facets_.size()) imp_->facets_.resize(index+1); ++f->facet::refs_; facet*& fpr = imp_->facets_[index]; if (fpr) --fpr->refs_; fpr = f; } Listing Eleven template inline Facet const& use_facet(locale const& loc) { size_t index = Facet::id.index_; locale::facet* fp; if (index >= loc.imp_->facets_.size() || (fp = loc.imp_->facets_[index]) == 0) throw bad_cast(); return static_cast(*fp); }