blob: 2ea13521f169bbc1079ff4e6bd6b59ca386fd397 [file] [log] [blame]
<HTML>
<HEAD>
<TITLE>Defining Traits and Facets for User-Defined Types</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="41-1.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="41-3.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>41.2 Defining Traits and Facets for User-Defined Types</H2>
<A NAME="idx967"><!></A>
<P>A user-defined type requires its own traits class, its own code conversion facet, and its own character classification facet. The traits class defines a conversion <SAMP>state_type</SAMP> and also defines operations such as copying arrays of the type and comparing arrays. The code conversion facet provides conversion to and from simple <SAMP>char</SAMP>s. The <SAMP>ctype</SAMP> facet provides character classification and manipulation routines, including the method for converting the new type to and from simple <SAMP>char</SAMP>s.</P>
<A NAME="idx968"><!></A>
<P>The following code shows a traits class declaration for <SAMP>Echar</SAMP>:</P>
<UL><PRE>
struct Etraits
{
typedef Echar char_type;
typedef long int_type;
typedef std::streamoff off_type;
typedef std::mbstate_t state_type;
typedef std::fpos&lt;state_type&gt; pos_type;
static void assign (char_type&amp; c1, const char_type&amp; c2);
static bool eq(const char_type&amp; c1,const char_type&amp; c2);
static bool lt (const char_type&amp; c1, const char_type&amp; c2);
static int compare (const char_type* s1, const char_type* s2,
std::size_t n);
static std::size_t length(const char_type *s);
static const char_type*
find (const char_type* s, int n, const char_type&amp; a);
static char_type* move (char_type* s1, const char_type* s2,
std::size_t n);
static char_type* copy(char_type *dst,const char_type *src,
std::size_t n);
static char_type* assign (char_type* s, std::size_t n,
const char_type&amp; a);
static int_type not_eof(const int_type&amp; c);
static char_type to_char_type(const int_type&amp; c);
static int_type to_int_type(const char_type&amp; c);
static bool eq_int_type(const int_type&amp; c1,const int_type&amp; c2);
static state_type get_state(pos_type pos);
static int_type eof();
};
</PRE></UL>
<P>See the <A HREF="../stdlibref/noframes.html"><I>C++ Standard Library Module Reference Guide</I></A> section on <A HREF="../stdlibref/char-traits.html">char_traits</A> for a complete description of the member functions in a traits class.</P>
<P>To create a new code conversion facet, you must inherit from the <SAMP>std::codecvt</SAMP> template and then override some or all the protected virtual functions. Iostreams calls the protected functions through the public interface defined for <SAMP>std::codecvt</SAMP>. You must also provide a constructor taking a single <SAMP>std::size_t</SAMP> argument, and initialize <SAMP>codecvt</SAMP> with that argument.</P>
<A NAME="idx969"><!></A>
<P>A code conversion facet for <SAMP>Echar</SAMP> has a declaration that looks like this:</P>
<UL><PRE>
class Ecodecvt : public std::codecvt&lt;Echar,char,Estate&gt;
{
public:
explicit Ecodecvt (std::size_t refs = 0)
: std::codecvt&lt;Echar,char,Estate&gt;(refs) { }
protected:
virtual result do_out(Estate&amp; state, const Echar* from,
const Echar* from_end,
const Echar*&amp; from_next,
char* to, char* to_limit,
char*&amp; to_next) const;
virtual result do_in(Estate&amp; state,
const char* from,
const char* from_end,
const char*&amp; from_next,
Echar* to, Echar* to_limit,
Echar*&amp; to_next) const;
virtual result do_unshift(Estate&amp; state,
char* to, char* to_limit,
char*&amp; to_next) const;
virtual int do_encoding() const throw();
virtual bool do_always_noconv() const throw();
virtual int do_length(Estate&amp; state, const char* from,
const char* end, size_t maxm) const;
virtual int do_max_length() const throw();
};
</PRE></UL>
<P>See <A HREF="40.html">Chapter&nbsp;40</A> on defining a code conversion facet for more details. Also see the <A HREF="../stdlibref/noframes.html"><I>C++ Standard Library Module Reference Guide</I></A> section on <A HREF="../stdlibref/codecvt.html">codecvt</A> for a complete description of member functions.</P>
<P>To create a character classification facet, you must inherit from the <SAMP>std::ctype</SAMP> template and provide implementations for all protected virtual functions. You must also provide a constructor taking a single <SAMP>std::size_t</SAMP> argument, and initialize <SAMP>std::ctype</SAMP> with that argument.</P>
<P>Note that the <SAMP>widen()</SAMP> functions define conversions from simple <SAMP>char</SAMP>s to the user-defined character type, and the narrow function provides conversions from the user-defined type to simple <SAMP>char</SAMP>s.</P>
<A NAME="idx970"><!></A>
<P>A character classification facet for <SAMP>Echar</SAMP> has a declaration that looks like this:</P>
<UL><PRE>
class Ectype : public std::ctype&lt;Echar&gt;
{
public:
typedef Echar char_type;
explicit Ectype (std::size_t refs = 0) :
std::ctype&lt;Echar&gt;(refs) { } // must pass refs onto
// the ctype constructor
protected:
virtual bool do_is(mask m, Echar c) const;
virtual const Echar* do_is(
const Echar* low,
const Echar* high,
mask* vec) const;
virtual const Echar* do_scan_is(
mask m, const Echar* low,
const Echar* high) const;
virtual const Echar* do_scan_not(
mask m, const Echar* low,
const Echar* high) const;
virtual Echar do_toupper(Echar e) const;
virtual const Echar* do_toupper(Echar* low,
const Echar* high) const;
virtual Echar do_tolower(Echar) const;
virtual const Echar* do_tolower(Echar* low,
const Echar* high) const;
virtual Echar do_widen(char) const;
virtual const char* do_widen(const char* lo,
const char* hi,
Echar* dest) const;
virtual char do_narrow(Echar, char dfault) const;
virtual const Echar* do_narrow(const Echar* lo,
const Echar* hi,char dfault,
char* dest) const;
};
</PRE></UL>
<BR>
<HR>
<A HREF="41-1.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="41-3.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>