blob: 1ee776c63106b88fc4ec6769aa6bd6db9ab21d3e [file] [log] [blame]
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed
with this work for additional information regarding copyright
ownership. The ASF licenses this file to you under the Apache
License, Version 2.0 (the License); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.
Copyright 1999-2007 Rogue Wave Software, Inc.
-->
<HTML>
<HEAD>
<TITLE>The Phone Number Facet Class Revisited</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="26-4.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="26-6.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library User's Guide</B></DIV>
<H2>26.5 The Phone Number Facet Class Revisited</H2>
<A NAME="idx593"><!></A>
<P>Let us now try to implement the phone number facet class. What does this facet need to know?</P>
<UL>
<LI><P CLASS="LIST">A facet needs to know its own locality, because a phone number is formatted differently for domestic and international use; for example, a German number looks like (089) / 636-48018 when used in Germany, but it looks like +1-49-89-636-48018 when used internationally.</P></LI>
<LI><P CLASS="LIST">A facet needs information about the prefix for dialing international numbers; for example, 011 for dialing foreign numbers from the US, or 00 from Germany, or 19 from France.</P></LI>
<LI><P CLASS="LIST">A facet needs access to a table of all country codes, so that one can enter a mnemonic for the country instead of looking up the respective country code. For example, I would like to say: "This is a phone number somewhere in Japan" without having to know what the country code for Japan is.</P></LI>
</UL>
<A NAME="idx594"><!></A>
<A NAME="2651"><H3>26.5.1 Adding Data Members</H3></A>
<A NAME="idx595"><!></A>
<P>The following class declaration for the telephone number formatting facet class is enhanced with a virtual member function <SAMP>do_put()</SAMP> which is delegated the task of actually constructing a phone number in a locale-dependent fashion in derived classes, as well as data members for the facet object's own locality, and its prefix for international calls (see <SAMP>//4</SAMP> and <SAMP>//5</SAMP> in the code below). Adding a table of country codes is omitted for the time being.</P>
<UL><PRE>
class phone_put: public std::locale::facet {
public:
static std::locale::id id;
typedef std::string string_type;
phone_put (std::size_t refs = 0)
: std::locale::facet (refs) { }
string_type put (const string_type &amp;cntryName,
const string_type &amp;areaCode,
const string_type &amp;extension) const {
return do_put (cntryName, areaCode, extension); // 1
}
protected:
phone_put (const string_type cntryName,
const string_type intlPrefix,
std::size_t refs = 0) // 2
: std::locale::facet(refs),
_cntryName(cntryName), _intlPrefix(intlPrefix);
virtual string_type
do_put(const string_type &amp;cntryName, // 3
const string_type &amp;areaCode,
const string_type &amp;extension) const { ... }
const string_type _cntryName; // 4
const string_type _intlPrefix; // 5
};
</PRE></UL>
<P>Note how this class serves as a base class for the facet classes that really implement a locale-dependent phone number formatting. Hence, the public constructor does not need to be extended, and a protected constructor is added instead (see <SAMP>//2</SAMP> above). The virtual member function <SAMP>do_put()</SAMP> is added (see <SAMP>//3</SAMP> above) so that it may be overridden in derived classes without hiding any overloads of the <SAMP>put()</SAMP> function if they existed, and also so that code can be placed in <SAMP>put()</SAMP> that will always be executed even though <SAMP>do_put()</SAMP> will be overridden (this is the same strategy used in the design of the standard facets). In this base class, <SAMP>do_put()</SAMP> could be implemented to construct phone numbers in a generic international fashion, e.g., "+49-89-636-48018". </P>
<A NAME="2652"><H3>26.5.2 Adding Country Codes</H3></A>
<A NAME="idx596"><!></A>
<P>Let us now deal with the problem of adding the international country codes that were omitted from the previous class declaration. These country codes can be held as a map of strings that associates the country code with a mnemonic for the country's name, as shown in <A HREF="8-2.html#Table&nbsp;14">Table&nbsp;14</A>:</P>
<A NAME="idx597"><!></A>
<H4><A NAME="Figure&nbsp;14">Figure&nbsp;14: Map associating country codes with mnemonics for countries' names</A></H4>
<P><IMG SRC="images/stdlibug-Locales12.gif" WIDTH=560 HEIGHT=206></P>
<A NAME="idx598"><!></A>
<P>In the following code, we add the table of country codes:</P>
<UL><PRE>
class phone_put: public std::locale::facet {
public:
...
class CodeMap
: public std::map&lt;std::string, std::string&gt; { // 1
public:
CodeMap() {
insert (std::make_pair ("De", "49"));
insert (std::make_pair ("Fr", "33"));
insert (std::make_pair ("US", "1"));
...
}
};
static const CodeMap* getStdCodes () { // 2
return &amp;_stdCodes;
}
protected:
...
static CodeMap _stdCodes; // 3
};
</PRE></UL>
<P>Since the table of country codes is a constant table that is valid for all telephone number facet objects, it is added as a static data member _<SAMP>stdCodes</SAMP> (see <SAMP>//3</SAMP>). The initialization of this data member is encapsulated in a class, <SAMP>CodeMap</SAMP> (see <SAMP>//1</SAMP>). For convenience, a function <SAMP>getStdCodes()</SAMP> is added to give access to the table (see <SAMP>//2</SAMP>).</P>
<P>Despite its appealing simplicity, however, having just one static country code table might prove too inflexible. Consider that mnemonics might vary from one locale to another due to different languages. Maybe mnemonics are not called for, and you really need more extended names associated with the actual country code.</P>
<P>In order to provide more flexibility, we can build in the ability to work with an arbitrary table. A pointer to the respective country code table can be provided when a facet object is constructed. The static table, shown in <A HREF="26-5.html#Figure&nbsp;15">Figure&nbsp;15</A> below, serves as a default:</P>
<A NAME="idx599"><!></A>
<H4><A NAME="Figure&nbsp;15">Figure&nbsp;15: Map associating country codes with country names</A></H4>
<P><IMG SRC="images/stdlibug-Locales13.gif" WIDTH=552 HEIGHT=209></P>
<A NAME="idx600"><!></A>
<P>Since we hold the table as a pointer, we need to pay attention to memory management for the table pointed to. We use a flag for determining whether the provided table needs to be deleted when the facet is destroyed. The following code demonstrates use of the table and its associated flag:</P>
<UL><PRE>
class phone_put: public std::locale::facet {
public:
phone_put (size_t refs = 0)
: std::locale::facet (refs), _codeMap (&amp;_stdCodes),
_delete_it (false) {}
protected:
phone_put (const string_type &amp;cntryName, // 1
const string_type &amp;intlPrefix,
const CodeMap* codeMap = 0,
bool delete_it = false,
size_t refs = 0)
: std::locale::facet (refs), _cntryName (cntryName),
_intlPrefix (intlPrefix), _codeMap (codeMap),
_delete_it (delete_it)
{
if (!codeMap) // 2
_codeMap = &amp;_stdCodes;
}
const CodeMap* getCodes () { // 3
return _codeMap;
}
public:
virtual ~phone_put () {
if (_delete_it)
delete _codeMap; // 4
}
...
protected:
bool _delete_it;
const CodeMap* _codeMap;
static CodeMap _stdCodes; // 5
...
};
</PRE></UL>
<TABLE CELLPADDING="3">
<TR VALIGN="top"><TD><SAMP>//1</SAMP></TD><TD>The constructor is enhanced to take a pointer to the country code table, together with the flag for memory management of the provided table.
<TR VALIGN="top"><TD><SAMP>//2</SAMP></TD><TD>If no table is provided, the static table is installed as a default.
<TR VALIGN="top"><TD><SAMP>//3</SAMP></TD><TD>For convenience, a function that returns a pointer to the current table is added.
<TR VALIGN="top"><TD><SAMP>//4</SAMP></TD><TD>The table is deleted if the memory management flags says so.
<TR VALIGN="top"><TD><SAMP>//5</SAMP></TD><TD>Protected data members are added to hold the pointer to the current country code table, as well as the associated memory management flag.
</TABLE>
<BR>
<HR>
<A HREF="26-4.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="26-6.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A>
<!-- Google Analytics tracking code -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-1775151-1";
urchinTracker();
</script>
<!-- end of Google Analytics tracking code -->
</BODY>
</HTML>