|
219 | 219 | function template
|
220 | 220 | \tcode{has_facet<Facet>()}.
|
221 | 221 | User-defined facets may be installed in a locale, and used identically as
|
222 |
| -may standard facets\iref{facets.examples}. |
| 222 | +may standard facets. |
223 | 223 |
|
224 | 224 | \pnum
|
225 | 225 | \begin{note}
|
|
5036 | 5036 | }
|
5037 | 5037 | \end{codeblock}
|
5038 | 5038 |
|
5039 |
| -\rSec2[facets.examples]{Program-defined facets} |
5040 |
| - |
5041 |
| -\pnum |
5042 |
| -A \Cpp{} program may define facets to be added to a locale and used identically as |
5043 |
| -the built-in facets. |
5044 |
| -To create a new facet interface, \Cpp{} programs simply derive from |
5045 |
| -\tcode{locale::facet} |
5046 |
| -a class containing a static member: |
5047 |
| -\tcode{static locale::id id}. |
5048 |
| - |
5049 |
| -\pnum |
5050 |
| -\begin{note} |
5051 |
| -The locale member function templates verify its type and storage class. |
5052 |
| -\end{note} |
5053 |
| - |
5054 |
| -\pnum |
5055 |
| -\begin{example} |
5056 |
| -Traditional global localization is still easy: |
5057 |
| - |
5058 |
| -\begin{codeblock} |
5059 |
| -#include <iostream> |
5060 |
| -#include <locale> |
5061 |
| -int main(int argc, char** argv) { |
5062 |
| - using namespace std; |
5063 |
| - locale::global(locale("")); // set the global locale |
5064 |
| - // imbue it on all the std streams |
5065 |
| - cin.imbue(locale()); |
5066 |
| - cout.imbue(locale()); |
5067 |
| - cerr.imbue(locale()); |
5068 |
| - wcin.imbue(locale()); |
5069 |
| - wcout.imbue(locale()); |
5070 |
| - wcerr.imbue(locale()); |
5071 |
| - |
5072 |
| - return MyObject(argc, argv).doit(); |
5073 |
| -} |
5074 |
| -\end{codeblock} |
5075 |
| -\end{example} |
5076 |
| - |
5077 |
| -\pnum |
5078 |
| -\begin{example} |
5079 |
| -Greater flexibility is possible: |
5080 |
| - |
5081 |
| -\begin{codeblock} |
5082 |
| -#include <iostream> |
5083 |
| -#include <locale> |
5084 |
| -int main() { |
5085 |
| - using namespace std; |
5086 |
| - cin.imbue(locale("")); // the user's preferred locale |
5087 |
| - cout.imbue(locale::classic()); |
5088 |
| - double f; |
5089 |
| - while (cin >> f) cout << f << endl; |
5090 |
| - return (cin.fail() != 0); |
5091 |
| -} |
5092 |
| -\end{codeblock} |
5093 |
| - |
5094 |
| -In a European locale, with input |
5095 |
| -\tcode{3.456,78}, |
5096 |
| -output is |
5097 |
| -\tcode{3456.78}. |
5098 |
| -\end{example} |
5099 |
| - |
5100 |
| -\pnum |
5101 |
| -This can be important even for simple programs, which may need to |
5102 |
| -write a data file in a fixed format, regardless of a user's preference. |
5103 |
| - |
5104 |
| -\pnum |
5105 |
| -\begin{example} |
5106 |
| -Here is an example of the use of locales in a library interface. |
5107 |
| - |
5108 |
| -\begin{codeblock} |
5109 |
| -// file: \tcode{Date.h} |
5110 |
| -#include <iosfwd> |
5111 |
| -#include <string> |
5112 |
| -#include <locale> |
5113 |
| - |
5114 |
| -class Date { |
5115 |
| -public: |
5116 |
| - Date(unsigned day, unsigned month, unsigned year); |
5117 |
| - std::string asString(const std::locale& = std::locale()); |
5118 |
| -}; |
5119 |
| - |
5120 |
| -std::istream& operator>>(std::istream& s, Date& d); |
5121 |
| -std::ostream& operator<<(std::ostream& s, Date d); |
5122 |
| -\end{codeblock} |
5123 |
| - |
5124 |
| -\pnum |
5125 |
| -This example illustrates two architectural uses of class |
5126 |
| -\tcode{locale}. |
5127 |
| - |
5128 |
| -\pnum |
5129 |
| -The first is as a default argument in |
5130 |
| -\tcode{Date::asString()}, |
5131 |
| -where the |
5132 |
| -default is the global (presumably user-preferred) locale. |
5133 |
| - |
5134 |
| -\pnum |
5135 |
| -The second is in the operators |
5136 |
| -\tcode{<<} and \tcode{>>}, |
5137 |
| -where a locale ``hitchhikes'' |
5138 |
| -on another object, in this case a stream, to the point where it |
5139 |
| -is needed. |
5140 |
| - |
5141 |
| -\begin{codeblock} |
5142 |
| -// file: \tcode{Date.C} |
5143 |
| -#include "Date" // includes \tcode{<ctime>} |
5144 |
| -#include <sstream> |
5145 |
| -std::string Date::asString(const std::locale& l) { |
5146 |
| - using namespace std; |
5147 |
| - ostringstream s; s.imbue(l); |
5148 |
| - s << *this; return s.str(); |
5149 |
| -} |
5150 |
| - |
5151 |
| -std::istream& operator>>(std::istream& s, Date& d) { |
5152 |
| - using namespace std; |
5153 |
| - istream::sentry cerberos(s); |
5154 |
| - if (cerberos) { |
5155 |
| - ios_base::iostate err = goodbit; |
5156 |
| - struct tm t; |
5157 |
| - use_facet<time_get<char>>(s.getloc()).get_date(s, 0, s, err, &t); |
5158 |
| - if (!err) d = Date(t.tm_day, t.tm_mon + 1, t.tm_year + 1900); |
5159 |
| - s.setstate(err); |
5160 |
| - } |
5161 |
| - return s; |
5162 |
| -} |
5163 |
| -\end{codeblock} |
5164 |
| -\end{example} |
5165 |
| - |
5166 |
| -\pnum |
5167 |
| -A locale object may be extended with a new facet simply by constructing |
5168 |
| -it with an instance of a class derived from |
5169 |
| -\tcode{locale::facet}. |
5170 |
| -The only member a \Cpp{} program must define is the static member |
5171 |
| -\tcode{id}, |
5172 |
| -which identifies your class interface as a new facet. |
5173 |
| - |
5174 |
| -\pnum |
5175 |
| -\begin{example} |
5176 |
| -Classifying Japanese characters: |
5177 |
| - |
5178 |
| -\begin{codeblock} |
5179 |
| -// file: \tcode{<jctype>} |
5180 |
| -#include <locale> |
5181 |
| -namespace My { |
5182 |
| - using namespace std; |
5183 |
| - class JCtype : public locale::facet { |
5184 |
| - public: |
5185 |
| - static locale::id id; // required for use as a new locale facet |
5186 |
| - bool is_kanji (wchar_t c) const; |
5187 |
| - JCtype() { } |
5188 |
| - protected: |
5189 |
| - ~JCtype() { } |
5190 |
| - }; |
5191 |
| -} |
5192 |
| - |
5193 |
| -// file: \tcode{filt.C} |
5194 |
| -#include <iostream> |
5195 |
| -#include <locale> |
5196 |
| -#include "jctype" // above |
5197 |
| -std::locale::id My::JCtype::id; // the static \tcode{JCtype} member declared above. |
5198 |
| - |
5199 |
| -int main() { |
5200 |
| - using namespace std; |
5201 |
| - using wctype = ctype<wchar_t>; |
5202 |
| - locale loc(locale(""), // the user's preferred locale ... |
5203 |
| - new My::JCtype); // and a new feature ... |
5204 |
| - wchar_t c = use_facet<wctype>(loc).widen('!'); |
5205 |
| - if (!use_facet<My::JCtype>(loc).is_kanji(c)) |
5206 |
| - cout << "no it isn't!" << endl; |
5207 |
| -} |
5208 |
| -\end{codeblock} |
5209 |
| - |
5210 |
| -\pnum |
5211 |
| -The new facet is used exactly like the built-in facets. |
5212 |
| -\end{example} |
5213 |
| - |
5214 |
| -\pnum |
5215 |
| -\begin{example} |
5216 |
| -Replacing an existing facet is even easier. |
5217 |
| -The code does not define a member |
5218 |
| -\tcode{id} |
5219 |
| -because it is reusing the |
5220 |
| -\tcode{numpunct<charT>} |
5221 |
| -facet interface: |
5222 |
| - |
5223 |
| -\begin{codeblock} |
5224 |
| -// file: \tcode{my_bool.C} |
5225 |
| -#include <iostream> |
5226 |
| -#include <locale> |
5227 |
| -#include <string> |
5228 |
| -namespace My { |
5229 |
| - using namespace std; |
5230 |
| - using cnumpunct = numpunct_byname<char>; |
5231 |
| - class BoolNames : public cnumpunct { |
5232 |
| - protected: |
5233 |
| - string do_truename() const { return "Oui Oui!"; } |
5234 |
| - string do_falsename() const { return "Mais Non!"; } |
5235 |
| - ~BoolNames() { } |
5236 |
| - public: |
5237 |
| - BoolNames(const char* name) : cnumpunct(name) { } |
5238 |
| - }; |
5239 |
| -} |
5240 |
| - |
5241 |
| -int main(int argc, char** argv) { |
5242 |
| - using namespace std; |
5243 |
| - // make the user's preferred locale, except for... |
5244 |
| - locale loc(locale(""), new My::BoolNames("")); |
5245 |
| - cout.imbue(loc); |
5246 |
| - cout << boolalpha << "Any arguments today? " << (argc > 1) << endl; |
5247 |
| -} |
5248 |
| -\end{codeblock} |
5249 |
| -\end{example} |
5250 |
| - |
5251 | 5039 | \rSec1[c.locales]{C library locales}
|
5252 | 5040 |
|
5253 | 5041 | \rSec2[clocale.syn]{Header \tcode{<clocale>} synopsis}
|
|
0 commit comments