blob: 9db7ffec05bd2d9fc168c44e3bb70f899bdd7281 [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>Creating a New Base Facet Class</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="25-5.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.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>25.6 Creating a New Base Facet Class</H2>
<A NAME="idx582"><!></A>
<P>At times you may need to add a facet object to a locale without displacing any of the existing facets. To do this, you must define a new base facet class.</P>
<P>Here is an example of a new facet class like that. It is a facet that provides a service to check whether a character is a German umlaut, that is, one of the special characters <SAMP>&auml;&ouml;&uuml;&Auml;&Ouml;&Uuml;</SAMP>.</P>
<UL><PRE>
class Umlaut : public std::locale::facet { //1
public:
static std::locale::id id; //2
Umlaut(std::size_t refs=0): std::locale::facet(refs) {} //3
bool is_umlaut(char c) const {return do_isumlaut(c);} //4
protected:
virtual bool do_isumlaut(char) const; //5
};
</PRE></UL>
<TABLE CELLPADDING="3">
<TR VALIGN="top"><TD><SAMP>//1</SAMP></TD><TD>All base facet classes must be derived from class <SAMP>std::locale::facet</SAMP>.
<TR VALIGN="top"><TD><SAMP>//2</SAMP></TD><TD>In addition, all base facet classes must contain a static member named <SAMP>id</SAMP>, of type <SAMP>std::locale::id</SAMP>. The locale system uses this object internally to identify the slot in locale objects where facets of this type are stored.
<BR><BR>(Derived facet classes do not contain their own <SAMP>id</SAMP> members. Instead, they inherit the member from a base facet class, and therefore are stored in the same slot as the base class.)
<TR VALIGN="top"><TD><SAMP>//3</SAMP></TD><TD>A <SAMP>const</SAMP> member function <SAMP>is_umlaut()</SAMP> is declared that returns the result of calling the protected virtual const function <SAMP>do_umlaut()</SAMP>. All facet member functions must be const since like locale objects, facets are immutable. Since the function template <SAMP>std::use_facet&lt;&gt;() </SAMP>returns a <SAMP>const </SAMP>reference to a facet, only member functions declared <SAMP>const</SAMP> are callable.
<TR VALIGN="top"><TD><SAMP>//4</SAMP></TD><TD>A member function <SAMP>is_umlaut()</SAMP> is declared that returns the result of calling the protected virtual function <SAMP>do_umlaut()</SAMP>.
<TR VALIGN="top"><TD><SAMP>//5</SAMP></TD><TD>The actual functionality of determining whether a character is an umlaut is implemented in a protected virtual member function. In general, all localization services in a facet should be implemented in virtual functions this way, so that derived facets can override them when necessary.
</TABLE>
<A NAME="idx583"><!></A>
<P>Now let's create a locale with a facet of the new type, as shown in <A HREF="25-6.html#Figure&nbsp;12">Figure&nbsp;12</A>:</P>
<A NAME="idx584"><!></A>
<H4><A NAME="Figure&nbsp;12">Figure&nbsp;12: Adding a new facet to a locale</A></H4>
<P><IMG SRC="images/locfig13.gif" WIDTH=419 HEIGHT=317></P>
<P>The code for this procedure is given below:</P>
<UL><PRE>
std::locale loc(std::locale(""), // native locale
new Umlaut); // the new facet //1
char c,d;
while (std::cin &gt;&gt; c){
d = std::use_facet&lt;std::ctype&lt;char&gt; &gt;(loc).tolower(c); //2
if (std::has_facet&lt;Umlaut&gt;(loc)) { //3
if (std::use_facet&lt;Umlaut&gt;(loc).is_umlaut(d)) //4
std::cout &lt;&lt; c &lt;&lt; "belongs to the German alphabet!" &lt;&lt; '\n';
}
}
</PRE></UL>
<TABLE CELLPADDING="3">
<TR VALIGN="top"><TD><SAMP>//1</SAMP></TD><TD>A locale object is constructed with an instance of the new facet class. The locale object has all facet objects from the native locale object, plus an instance of the new facet class <SAMP>Umlaut</SAMP>.
<TR VALIGN="top"><TD><SAMP>//2</SAMP></TD><TD>Let's assume our new umlaut facet class is somewhat limited; it can handle only lower case characters. Thus we have to convert each character to a lower case character before we hand it over to the umlaut facet object. This is done by using a <SAMP>std::ctype</SAMP> facet object's service function <SAMP>tolower()</SAMP>.
<TR VALIGN="top"><TD><SAMP>//3</SAMP></TD><TD>Before we use the umlaut facet object, we check whether such an object is present in the locale. In a toy example like this it is obvious, but in a real application it is advisable to check for the existence of nonstandard facet objects before trying to use them.
<TR VALIGN="top"><TD><SAMP>//4</SAMP></TD><TD>The umlaut facet object is used, and its member function <SAMP>is_umlaut()</SAMP> is called. Note that the syntax for using this newly contrived facet object is exactly like the syntax for using the standard <SAMP>ctype</SAMP> facet.
</TABLE>
<BR>
<HR>
<A HREF="25-5.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.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>