Default locale Arguments for Iostreams 26-Jan-95 -------------------------------------- X3J16/95-0026 by Nathan Myers, myersn@roguewave.com WG21/N0626 Rogue Wave Software Examples of using locales with iostreams have thus far referred to "imbuing" locales into existing iostreams. Each iostream begins its life with a locale, however, and it seems better to offer the choice at construction time. Of course C++ provides an easy and backward-compatible means to add such a choice, via default arguments. Specifically, we can change constructors for each class in the ios hierarchy as follows: basic_ios::basic_ios(basic_streambuf*, locale const& = DEFAULT); basic_istream::basic_istream(basic_streambuf*, locale const& = DEFAULT); basic_ostream::basic_ostream(basic_streambuf*, locale const& = DEFAULT); [ etc. ] This begs the question, of course, what to specify in place of DEFAULT. The obvious choices are: 0. Don't provide such an argument. Let the streams default to one of the following three choices, invisibly. 1. The status quo. "DEFAULT" is replaced by "locale::classic()", the C/ASCII/American locale. Users writing new code, or internationalizing old code, can decide whether a stream is user-visible, and choose the appropriate locale, while existing code works (perhaps unpleasantly formatted) as before. 2. The approach taken in C. "DEFAULT" becomes "locale()", a copy of the current global locale. Users who need a stable format specify the appropriate locale. Streams created in existing code automatically use users' preferred formats, regardless of the source or destination of the data. A third choice was suggested by Tom Plum, a sort of compromise. 3. Invent a third global locale, called "locale::ios()". A copy of this locale is passed by default to each newly created stream. Class locale gets a new static member function, locale::ios( locale const&), to set this global value. Library users choose between alternatives 1 and 2 above at runtime. Discussion ---------- The argument for the original specification (alternatives 0/1) was that existing code works that way, and that streams opened in libraries, where source code is inaccessible to users, may depend on particular data formats fixed by history. Because these data formats often are not seen by users, consistency of format may be more important than responding to users' preferences; errors resulting from such format changes can be difficult to trace. Formats that are seen Default locale Arguments for Iostreams 26-Jan-95 Page 2 of 3 -------------------------------------- 95-0026/N0626 by users, on the other hand, are easily found and fixed, and until fixed are generally more embarrassing than serious. The argument for alternative 2 is that many of these same libraries fail to respond to users' formatting preferences, now, and that they could be easily and transparently fixed by changing the default. Furthermore, the default would match C's default and therefore be more familiar to those used to C's internationalization facilities. Non-user-visible streams are assumed to be rare and not so difficult to locate and fix to use a particular format. Streams have been avoided in many such places, anyhow, because iostream formatting (like printf's) has actually varied more-or-less randomly with the current global locale and therefore could not be counted upon for stability. (Libraries that used streams in such instances have not been safe to use in internationalized programs, and would continue to be unsafe in them.) The argument for alternative 3 is that it allows the library user a choice between alternatives 1 and 2. Analysis: --------- It is impossible to speak authoritatively on the relative merits of alternatives 1 and 2 without trying both in a substantial body of code. As we have no opportunity to do this, we must muddle along and choose according to whatever criteria we can discover. Alternative 3 seems to offer an easy way out -- we don't need to decide, because we can let each user decide. As is common with compromises, however, arguments against it are easy to discover: - it adds significant complexity to the library by adding another global variable object. - its use may evoke the worst of the consequences predicted for both of alternatives 1 and 2, in (e.g.) libraries that open _both_ user-visible and hidden streams. - it offers library writers no more stability than choice 2, and library users no assurance that changing the global iostream default is compatible with any particular library. - it enshrines in the standard a visible artifact of our indecision. Alternative 2 promises to fix some currently-broken code at no cost, while leaving libraries not currently safe for use in internationalized programs still unsafe. Its semantics is familiar to the community used to locale features, and is the most reasonable for someone viewing the standard from a future viewpoint. Alternative 1 promises to make existing many libraries locale-safe anywhere (including places where they would break now) but does not offer to internationalize anything automatically. It leaves a somewhat unfortunate legacy to the future, with streams defaulting to a parochial format only historically appropriate. Default locale Arguments for Iostreams 26-Jan-95 Page 3 of 3 -------------------------------------- 95-0026/N0626 Summary: -------- Alternative 1 is safest, and preserves old code best; alternative 2 is bolder about declaring non-internationalized code "already broken", but will be looked on by future generations as cleanest; alternative 3 hedges our bets at the cost of adding significant complexity to the library.