URL
https://opencores.org/ocsvn/scarts/scarts/trunk
Subversion Repositories scarts
[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libstdc++-v3/] [docs/] [html/] [ext/] [pb_assoc/] [ms_gen.html] - Rev 20
Compare with Previous | Blame | View Log
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Mapping-Semantics Genericity</title> <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </head> <body bgcolor = "white"> <h1>Mapping-Semantics</h1> <p> This section describes genericity over different mapping-semantics. It is organized as follows. </p> <ol> <li><a href = "#intro">Introduction</a></li> <li><a href = "#ds_policy">Data Types as a Policy</a></li> <li><a href = "#problem">The Basic Problem</a></li> <li><a href = "#mapping_level">Mapping Levels</a></li> <li><a href = "#ms_traits">Tags and Traits</a></li> <li><a href = "#drawbacks">Drawbacks</a></li> </ol> <h2><a name = "intro">Introduction</a></h2> <p> <a href = "motivation.html#mapping_semantics">Motivation::Mapping Semantics</a> discussed scalability issues with the STL's non-unique-mapping associative containers; non-unique association inherently embeds linked-lists in associative containers resulting in scalability problems and other problems. </p> <p> In <tt>pb_assoc</tt>, all containers have unique-key semantics. Each key is uniquely mapped to "something". </p> <h2><a name = "ds_policy">Data Types as a Policy</a></h2> <p> All associative-containers in <tt>pb_assoc</tt> are parameterized by a data type. <i>E.g.,</i> <a href = "cc_hash_assoc_cntnr.html">cc_hash_assoc_cntnr</a> is parameterized as </p> <pre> <b>template</b>< <b>typename</b> Key, <b>typename</b> Data, ...> <b>class</b> <a href = "cc_hash_assoc_cntnr.html">cc_hash_assoc_cntnr</a>; </pre> <p> There are no separate classes for maps, sets, multimaps, and multisets (as the STL has). Rather, the mapping-semantic is set by specifying the <tt>Key</tt> parameter. </p> <ol> <li> If <tt>Data</tt> is any type (<i>e.g.</i>, <tt><b>int</b></tt> or <tt>std::string</tt>), then the container is a "map" - it maps each <tt>Key</tt> object to a <tt>Data</tt> object. </li> <li> If <tt>Data</tt> is <a href = "null_data_type.html"><tt>null_data_type</tt></a>, then the container is a "set" - it stores each <tt>Key</tt> object. In this case, each <tt>Key</tt> object is not really mapped to anything (except, implicitly, to the fact that it is stored in the container object). </li> <li> If <tt>Data</tt> is <a href = "compound_data_type.html">compound_data_type</a><tt><Cntnr></tt>, then the container is a "multimap" - it maps each <tt>Key</tt> object into a <tt>Cntnr</tt> object. This structure is recursive - <tt>Cntnr</tt> itself can be a "map", "set", "multimap", and so forth. </li> </ol> <p> Each container derives from one of the three containers in the oval of Figure <a href = "#ms_cd"> Data-types as a policy </a>. </p> <ol> <li><a href = "basic_assoc_cntnr.html"><tt>basic_assoc_cntnr</tt></a> is the base for most instantiations of a container's <tt>Data</tt> paramter. This base includes the definition of <tt>data_type</tt>, and supports <tt><b>operator</b>[]</tt>. </li> <li><a href = "basic_assoc_cntnr_no_data.html"><tt>basic_assoc_cntnr</tt></a> is the base for a <a href = "null_data_type"><tt>null_data_type</tt></a> instantiation of a container's <tt>Data</tt> paramter. This base lacks the definition of <tt>data_type</tt>, and does not support <tt><b>operator</b>[]</tt>. <li><a href = "basic_assoc_cntnr_compound_data.html"><tt>basic_assoc_cntnr</tt></a> is the base for a <a href = "compound_data_type.html"><tt>compound_data_type</tt></a><tt><Cntnr></tt> instantiation of a container's <tt>Data</tt> paramter. This base includes the definition of <tt>data_type</tt>, and supports <tt><b>operator</b>[]</tt>. It further supports some advanced functionality described in the remainder of this section. </ol> <h6 align = "center"> <a name = "ms_cd"> <img src = "ms_cd.jpg" width = "70%" alt = "no image"> </h6> </a> <h6 align = "center"> Data-types as a policy. </h6> <h2><a name = "problem">The Basic Problem</a></h2> <p> Consider a <tt>pb_assoc</tt> "multimap" mapping integers to characters. Since a <tt>pb_assoc</tt> "multimap" is a "map" of "sets", if <tt>m</tt> is an object of this type, it is not possible to directly use <tt>m.insert(std::make_pair(2, 'b')</tt> (however, it is possible to directly use <tt>m[2].insert('b')</tt>). In would be nice if this method whould be supported. </p> <p> Put differently, while the <tt>pb_assoc</tt> "multimap" can be viewed logically as the collection </p> <p> { <tt><b>int</b></tt> → {<tt><b>char</b></tt>} }, </p> <p> It would be nice if it could simultaneously be viewed as the collection </p> <p> { (<tt><b>int</b></tt>, <tt><b>char</b></tt>) }, </p> <p><i>i.e.</i>, a "set" of pairs.</p> <p> In more general terms, it would be nice to be able to simultaneously view a collection </p> <p> { key_type_0 → { key_type_1 → { key_type_2 → { key_type_3 → { ... }}}}} </p> <p> as each of the following: </p> <p> { (key_type_0, key_type_1) → { key_type_2 &rarr { key_type_e → { ... }}}}, </p> <p> { (key_type_0, key_type_1, key_type_2) &rarr { key_type_3 → { ... }}} </p> <p> { (key_type_0, key_type_1, key_type_2, key_type_3 ) &rarr { }} </p> <p> ... </p> <p> <a href = #mapping_level">Mapping_Levels</a> discusses the mechanism for these multiple views in <tt>pb_assoc</tt> </p> <h2><a name = "mapping_level">Mapping Levels</a></h2> <p> Each associative container in <tt>pb_assoc</tt> has a <i>mapping level</i>. The mapping level is defined by the instantiation of a container's <tt>Data</tt> parameter: </p> <ol> <li> If the <tt>Data</tt> parameter is instantiated by <a href = "null_data_type.html"><tt>null_data_type</tt></a> (<i>i.e.</i>, the container is a "set"), then the mapping level is 1. </li> <li> If the <tt>Data</tt> parameter is instantiated by <a href = "compound_data_type.html">compound_data_type</a><tt><Cntnr></tt> (<i>i.e.</i>, the container is a "multimap"), then the mapping level is 1 + the mapping level of <tt>Cntnr</tt>. </li> <li> If the <tt>Data</tt> parameter is instantiated by any other type, <i>e.g.</i>, <tt><b>char</b></tt> (<i>i.e.</i>, the container is a "map"), then the mapping level is 1. </li> </ol> <p> Containers can be rebound, at compile time, to different mapping levels. The compound data-type specialization <a href = "basic_assoc_cntnr_compound_data.html"><tt>basic_assoc_cntnr</tt></a> defines internally </p> <pre> <b>template</b>< <b>int</b> Mapping_Level> <b>struct</b> rebind { <b>typedef</b> ... other; }; </pre> <p> (which is similar to the STL's allocator rebind mechanism). the type <tt>other</tt> is the view of the container with mapping level <tt>Mapping_Level</tt>. The container can be safely cast to <tt>other</tt>. </p> <p> As an example, consider the type </p> <pre> <b>typedef</b> <a href = "cc_hash_assoc_cntnr.html">cc_hash_assoc_cntnr</a>< <b>int</b>, <a href = "compound_data_type.html">compound_data_type</a>< <a href = "tree_assoc_cntnr.html">tree_assoc_cntnr</a>< <b>char</b>, <a href = "null_data_type.html"><tt>null_data_type</tt></a>> > > cntnr_t; </pre> <p> which is a "map" mapping each <tt><b>int</b></tt> to a "set" of <tt><b>char</b></tt>s. In this case, <tt>cntnr_t</tt> has mapping level 2. </p> <p> An object of type <tt>cntnr_t</tt> cannot support <tt>insert(std::make_pair(2, 'b'));</tt>. On the other hand, the following code snippet shows how to do so: </p> <pre> cntnr_t c; <b>typedef</b> t::rebind<1>::other t_; ((t_ &)c).insert(std::make_pair(2, 'b')); </pre> <p> <a href = "../example/mapping_level_example.cpp"><tt>mapping_level_example.cpp</tt></a> shows a more detailed example. </p> <h2><a name = "ms_traits">Tags and Traits</a></h2> <p> It is, of course, beneficial to query types for their mapping semantics. </p> <p> Each container defines internally the type <tt>ms_category</tt> as its mapping-semantics tag (hopefully this name is not copyrighted by some major corporation). The possible tags, shown in Figure are the following: </p> <ol> <li> <a href = "basic_ms_tag.html"><tt>basic_ms_tag</tt></a> is a basic mapping-semantics tag. It is the type defined by "set"s. </li> <li> <a href = "data_enabled_ms_tag.html"><tt>data_enabled_ms_tag</tt></a> is a mapping-semantics tag of types that have data. It is the type defined by "map"s. </li> <li> <a href = "compound_data_enabled_ms_tag.html"><tt>compound_data_enabled_ms_tag</tt></a> is a mapping-semantics tag of types that have compound data. It is the type defined by "multimap"s. </li> </ol> <p> Additionally, a container's mapping semantics can be queried by traits. For any container <tt>Cntnr</tt>, </p> <pre> <a href = "ms_traits.html">ms_traits</a><Cntnr>::mapping_level </pre> <p> indicates the mapping level of the container, for example. </p> <h2><a name = "drawbacks">Drawbacks</a></h2> <tt>pb_assoc</tt>'s mapping-semantics design has some drawbacks compared to that of the STL. <h3>Equivalent, Non-Identical Keys</h3> <p> The STL's multimaps and multisets allow storing equivalent, non-identical keys [<a href = "references.html#kleft00sets">kleft00sets</a>]. For example, assume a bank maintains a data structure monitoring the accounts opened by each person. This could be modeled as the following: </p> <pre> <i>// Name type.</i> <b>typedef</b> std::string name; <i>// Account-id type.</i> <b>typedef</b> <b>unsigned long</b> account_id; <i>// Association between a name and an account id.</i> <b>class</b> opened_info { <b>public</b>: ... <i>// Comparison operator.</i> <b>bool</b> <b></b>operator<</b> (<b>const</b> opened_info &r_other) { <i>Comparison is defined as the comparison of the names.</i> <b>return</b> m_name < r_other.m_name; } <b>private</b>: name m_name; account_id m_acc_id; }; <i>// A multiset of opened accounts.</i> <b>typedef</b> std::multiset< opened_info> all_opened_info; </pre> <p> <tt>std::multiset</tt> can accomodate multiple equivalent, non-identical <tt>opened_info</tt> - those with the same name but different account id. </p> <p> In <tt>pb_assoc</tt>, however, non-unique mapping is unsupported. The equivalent to the above could be </p> <pre> <b>typedef</b> tree_assoc_cntnr< name, compound_data_type< cc_hash_assoc_cntnr< account_id> > > all_opened_info; </pre> <p> The drawback lies in the fact that the data stored in <tt>all_opened_info</tt> is less encapsulated - an <tt>opened_info</tt> object needs to be constructed when a specific name and account are found, and an <tt>opened_info</tt> object needs to be decomposed into <tt>name</tt> and <tt>account_id</tt> objects when it is inserted into a <tt>all_opened_info</tt> object. </p> <p> It should be noticed however, that the above drawbacks - construction and decomposition are constant-time additive drawbacks. The drawbacks of the STL's associative containers are in terms of orders of growth. </p> <h3>Definition of <tt>value_type</tt></h3> <p> The STL's associative containers contain a pleasingly uniform definition of the <tt>value_type</tt> of a container. If a container is parameterized by <tt>key</tt> as its <tt>Key</tt>, and <tt>data</tt> as its <tt>Data</tt>, then its <tt>value_type</tt> is <tt>std::pair<<b>const</b> key, data></tt>; for example, the <tt>value_type</tt> of <tt>std::map<<b>int</b>, <b>char</b>></tt> is <tt>std::pair<<b>const int</b>, <b>char</b>></tt>. Futhermore, the <tt>value_type</tt> of a container and the <tt>value_type</tt> of the container's iterators are identical. </p> <p> In <tt>pb_assoc</tt>, conversely, the rules are more complex. </p> <p> For one, a container's <tt>value_type</tt> is, in general <tt>std::pair<<b>const</b> Key, Data></tt>, but if <tt>Data</tt> is <tt>null_data_type</tt>, then the <tt>value_type</tt> is <tt>Key</tt>, and if <tt>Data</tt> is <tt>compound_data_type<Cntnr></tt>, then the <tt>value_type</tt> is <tt>std::pair<<b>const</b> Key, Cntnr></tt>. </p> <p> Futhermore, assume that <tt>Cntnr</tt> is an associative container with more than a single mapping level, and let <tt>Cntnr_</tt> be defined as </p> <pre> <b>typedef</b> <b>typename</b> Cntnr::<b>template</b> rebind<i>::other</tt> Cntnr_; </pre> <p> <i>i.e.</i>, the container rebound to a different mapping level. In this case, the <tt>value_type</tt> of the rebound container is not the <tt>value_type</tt> of the rebound container's iterators. <i>I.e.</i>, it is <emph>not</emph> true that <tt><b>typename</b> Cntnr_::value_type</tt> is the same as <tt><b>typename</b> Cntnr_::iterator::value_type</tt>. This complication never exists for the STL's container. </p> <h6 align = "center"> <a name = "reference_iterator"> <img src = "reference_iterator.jpg" width = "70%" alt = "no image"> </h6> </a> <h6 align = "center"> Iterator of a rebound type. </h6> <h3>Multisets</h3> <p> <tt>pb_assoc</tt> does not contain a "multiset" type. The closest equivalent is mapping keys to non-negative integral types, <i>e.g.</i>, <tt>size_t</tt>. </p> </body> </html>