123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
- <title>Identifier subtypes</title>
- <link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
- <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
- <link rel="home" href="../index.html" title="Chapter 1. The Variadic Macro Data Library 1.9">
- <link rel="up" href="../index.html" title="Chapter 1. The Variadic Macro Data Library 1.9">
- <link rel="prev" href="vmd_modifiers/vmd_modifiers_single.html" title="Modifiers and the single-element sequence">
- <link rel="next" href="vmd_useful.html" title="Useful variadic macros not in Boost PP">
- </head>
- <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
- <table cellpadding="2" width="100%"><tr>
- <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
- <td align="center"><a href="../../../../../index.html">Home</a></td>
- <td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
- <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
- <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
- <td align="center"><a href="../../../../../more/index.htm">More</a></td>
- </tr></table>
- <hr>
- <div class="spirit-nav">
- <a accesskey="p" href="vmd_modifiers/vmd_modifiers_single.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_useful.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
- </div>
- <div class="section">
- <div class="titlepage"><div><div><h2 class="title" style="clear: both">
- <a name="variadic_macro_data.vmd_identifier_subtype"></a><a class="link" href="vmd_identifier_subtype.html" title="Identifier subtypes">Identifier
- subtypes</a>
- </h2></div></div></div>
- <p>
- Identifiers are the low-level data types which macro programmers use to pass
- preprocessing data most often. As we have seen VMD has a system for registering
- and detecting identifiers so that they can be parsed as part of preprocessor
- data. This system also includes comparing identifiers for equality or inequality
- using BOOST_VMD_EQUAL/BOOST_VMD_NOT_EQUAL and matching identifiers using identifier
- modifiers in BOOST_VMD_IS_IDENTIFIER and BOOST_VMD_ELEM. Together these facilities
- provide a rich set of functionality for handling identifiers in macros.
- </p>
- <p>
- Both numbers and v-types are subtypes of identifiers, and can both be individually
- recognized as data types of their own or worked with as identifiers using the
- identifier facilities already mentioned. Numbers, in particular, also have
- a rich set of functionality within the Boost PP library. As subtypes numbers
- and v-types can be used as filter modifiers and can be returned as specific
- types either when invoking BOOST_VMD_GET_TYPE or when using return type modifiers.
- Furthermore VMD recognizes their individual v-types, BOOST_VMD_TYPE_NUMBER
- and BOOST_VMD_TYPE_TYPE, as VMD data when parsing sequences.
- </p>
- <p>
- It is possible for the end-user to define his own identifier subtype. This
- is called a "user-defined subtype". Once a user-define subtype is
- created all the generic type facilities of VMD which subtypes such as a number
- or a v-type possess is automatically available for that user-defined subtype.
- </p>
- <h4>
- <a name="variadic_macro_data.vmd_identifier_subtype.h0"></a>
- <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.defining_a_subtype"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.defining_a_subtype">Defining
- a subtype</a>
- </h4>
- <p>
- In order to define a user-defined subtype a number of steps need to be followed.
- These steps will be explained in detail further below:
- </p>
- <div class="orderedlist"><ol class="orderedlist" type="1">
- <li class="listitem">
- Register and pre-detect all identifiers of that subtype.
- </li>
- <li class="listitem">
- Register and pre-detect a v-type name for that subtype.
- </li>
- <li class="listitem">
- Subset register all identifiers of the subtype.
- </li>
- <li class="listitem">
- Subset register the v-type name for the subtype.
- </li>
- </ol></div>
- <p>
- When we do the above, it is best to put all the macros in a single header file
- and always include that header file when we work generically with our user-defined
- subtype.
- </p>
- <h4>
- <a name="variadic_macro_data.vmd_identifier_subtype.h1"></a>
- <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_all_iden"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_all_iden">Register
- and pre-detect all identifiers of that subtype</a>
- </h4>
- <p>
- Registering and pre-detecting all of the identifiers of that subtype is exactly
- the same as registering and pre-detecting any identifier.
- </p>
- <p>
- Let's create some identifiers based for use in the mythical "udef"
- library. We will put all our macros in the header file udef_vmd_macros.hpp.
- </p>
- <p>
- We will need distinct names for the identifiers in our library, so we will
- append UDEF_ to our identifier names to make them unique. Our udef library
- deals in geometrical shapes so we will create a user-defined subtype which
- consists of identifiers for the various shapes our udef library can manipulate
- in their macros. So our identifier registrations and pre-detections placed
- in our header file will be:
- </p>
- <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_CIRCLE</span> <span class="special">(</span><span class="identifier">UDEF_CIRCLE</span><span class="special">)</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_SQUARE</span> <span class="special">(</span><span class="identifier">UDEF_SQUARE</span><span class="special">)</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_TRIANGLE</span> <span class="special">(</span><span class="identifier">UDEF_TRIANGLE</span><span class="special">)</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_UDEF_HEXAGON</span> <span class="special">(</span><span class="identifier">UDEF_HEXAGON</span><span class="special">)</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_CIRCLE_UDEF_CIRCLE</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_SQUARE_UDEF_SQUARE</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_TRIANGLE_UDEF_TRIANGLE</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_UDEF_HEXAGON_UDEF_HEXAGON</span>
- </pre>
- <h4>
- <a name="variadic_macro_data.vmd_identifier_subtype.h2"></a>
- <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_a_v_type"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.register_and_pre_detect_a_v_type">Register
- and pre-detect a v-type name for that subtype</a>
- </h4>
- <p>
- We need to create a unique v-type name for our user-defined subtype. The name
- does not have to begin with BOOST_VMD_TYPE_ but it should be unique. Since
- BOOST_VMD_TYPE_ is the common beginning of all v-types we will use it for consistency
- but will append to it UDEF_SHAPES to give it a uniqueness which should not
- be duplicated:
- </p>
- <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_REGISTER_BOOST_VMD_TYPE_UDEF_SHAPES</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_DETECT_BOOST_VMD_TYPE_UDEF_SHAPES_BOOST_VMD_TYPE_UDEF_SHAPES</span>
- </pre>
- <h4>
- <a name="variadic_macro_data.vmd_identifier_subtype.h3"></a>
- <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.subtype_register_all_identifiers"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.subtype_register_all_identifiers">Subtype
- register all identifiers of the subtype</a>
- </h4>
- <p>
- The macro to register an identifier subset starts with BOOST_VMD_SUBTYPE_REGISTER_
- and you append to it each identifier in the subset. This is very much like
- the way you use the BOOST_VMD_REGISTER_ macro. The difference is that unlike
- the BOOST_VMD_REGISTER_ macro, which expands to a tuple whose single element
- is the identifier, the BOOST_VMD_SUBTYPE_REGISTER_ expands to a tuple of two
- elements where the first element is the subtype v-type and the second element
- is the identifier.
- </p>
- <p>
- For our udef user-defined subtype this would be:
- </p>
- <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_CIRCLE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">)</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_SQUARE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_SQUARE</span><span class="special">)</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_TRIANGLE</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_TRIANGLE</span><span class="special">)</span>
- <span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_UDEF_HEXAGON</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">,</span><span class="identifier">UDEF_HEXAGON</span><span class="special">)</span>
- </pre>
- <h4>
- <a name="variadic_macro_data.vmd_identifier_subtype.h4"></a>
- <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.subtype_register_the_v_type_name"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.subtype_register_the_v_type_name">Subtype
- register the v-type name for the subtype</a>
- </h4>
- <p>
- Doing a subset register of the actual udef v-type is fairly easy once we understand
- how to register an identifier subset. The only particular thing to realize
- is that the type of any v-type is the v-type BOOST_VMD_TYPE_TYPE. So our subset
- register of our new v-type BOOST_VMD_TYPE_UDEF_SHAPES is:
- </p>
- <pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">BOOST_VMD_SUBTYPE_REGISTER_BOOST_VMD_TYPE_UDEF_SHAPES</span> <span class="special">(</span><span class="identifier">BOOST_VMD_TYPE_TYPE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span>
- </pre>
- <h4>
- <a name="variadic_macro_data.vmd_identifier_subtype.h5"></a>
- <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.using_our_identifier_subset"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.using_our_identifier_subset">Using
- our identifier subset</a>
- </h4>
- <p>
- Once we have added all of the above object-like macros for defining our user-defined
- subtype to the udef_vmd_macros.hpp header file we have a new data type which
- we can use generically just like we can use numbers or v-types generically.
- It is important to include the header udef_vmd_macros.hpp in some translation
- unit whenever we need the VMD functionality for our new data type. So in our
- examples we will assume that an '#include udef_vmd_macros.hpp' precedes each
- example.
- </p>
- <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">get_type</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
- <span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE</span> <span class="identifier">UDEF_SQUARE</span>
- <span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE2</span> <span class="number">217</span>
- <span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE3</span> <span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span>
- <span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE4</span> <span class="identifier">BOOST_VMD_TYPE_NUMBER</span>
- <span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_UDEF_SHAPES'</span>
- <span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE2</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_NUMBER'</span>
- <span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE3</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_TYPE'</span>
- <span class="identifier">BOOST_VMD_GET_TYPE</span><span class="special">(</span><span class="identifier">A_SEQUENCE4</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'BOOST_VMD_TYPE_TYPE'</span>
- </pre>
- <p>
- Here we see that when we use our BOOST_VMD_GET_TYPE macro on a single-element
- sequence which is one of our user-defined subtype values we correctly get back
- our user-defined subtype's v-type, just like we do when we ask for the type
- of a number. Also when we use our BOOST_VMD_GET_TYPE macro on our user-defined
- subtype's v-type itself we correctly get back the type of all v-types, which
- is BOOST_VMD_TYPE_TYPE, just like we do when we ask for the type of the v-type
- of a number.
- </p>
- <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">elem</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
- <span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE5</span> <span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">)</span> <span class="identifier">UDEF_TRIANGLE</span>
- <span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="identifier">A_SEQUENCE5</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_UDEF_SHAPES,UDEF_TRIANGLE)'</span>
- <span class="identifier">BOOST_VMD_ELEM</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="identifier">A_SEQUENCE5</span><span class="special">,</span><span class="identifier">BOOST_VMD_RETURN_TYPE</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'(BOOST_VMD_TYPE_TUPLE,(1,2))'</span>
- </pre>
- <p>
- Here we see that we can use the return type modifier to get back both the type
- and the value in a two-element tuple for our user-defined subtype just as we
- so for any other type.
- </p>
- <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">vmd</span><span class="special">/</span><span class="identifier">equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
- <span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE6</span> <span class="identifier">UDEF_CIRCLE</span>
- <span class="preprocessor">#define</span> <span class="identifier">A_SEQUENCE7</span> <span class="number">168</span>
- <span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE6</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_UDEF_SHAPES</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'1'</span>
- <span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE6</span><span class="special">,</span><span class="identifier">UDEF_CIRCLE</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_LIST</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'0'</span>
- <span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE7</span><span class="special">,</span><span class="number">168</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_NUMBER</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'1'</span>
- <span class="identifier">BOOST_VMD_EQUAL</span><span class="special">(</span><span class="identifier">A_SEQUENCE7</span><span class="special">,</span><span class="number">168</span><span class="special">,</span><span class="identifier">BOOST_VMD_TYPE_SEQ</span><span class="special">)</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="char">'0'</span>
- </pre>
- <p>
- Here we can see that we can use the filter modifier with our user-defined subtype's
- v-type just as we can do with any other v-type, such as the number v-type.
- </p>
- <p>
- In all respects once we define our subtype and provide those definitions in
- a header file, our user-defined subtype acts like any other v-type in our system.
- Since VMD functionality is largely based on being able to recognize the type
- of data in macro input being able to define another 'type', as an identifier
- subtype, which VMD understands has value for the macro programmer.
- </p>
- <h4>
- <a name="variadic_macro_data.vmd_identifier_subtype.h6"></a>
- <span class="phrase"><a name="variadic_macro_data.vmd_identifier_subtype.uniqueness_of_identifier_subtype"></a></span><a class="link" href="vmd_identifier_subtype.html#variadic_macro_data.vmd_identifier_subtype.uniqueness_of_identifier_subtype">Uniqueness
- of identifier subtype values and v-type</a>
- </h4>
- <p>
- When we define a new identifier subtype we need to be careful that the values
- of that subtype and its actual v-type are unique identifiers within any translation
- unit. This is the main difference between just defining identifiers and defining
- an identifier subtype.
- </p>
- <p>
- Recall that when we just register and pre-detect identifiers we will have no
- problems if the same identifiers already have been registered and pre-detected
- within the same translation unit. This is because we are just redefining the
- exact same macro if this is the case.
- </p>
- <p>
- But with identifier subtypes, when we use the BOOST_VMD_SUBTYPE_REGISTER_ macro
- to associate our subtype's v-type with our subtype identifiers, we will have
- problems if someone else has also defined an identifier subtype using the same
- identifiers as we use since we will be redefining the same object-like macro
- name with a different expansion. Even if someone else has registered/pre-detected
- an identifier we are using for out subtype without defining a subtype based
- on that identifier we will be causing a problem defining our subtype because
- VMD macros which generically return the type of a sequence or sequence element
- will return our subtype as the type rather than just BOOST_VMD_TYPE_IDENTIFIER
- which some programmer might expect.
- </p>
- <p>
- The gist of this is that if we define a user-defined subtype its identifiers
- need to be unique within a given translation unit, and yet unique names make
- it harder for an end-user to use macros more naturally. In our given example
- with the mythical udef library we used identifiers such as 'UDEF_CIRCLE' etc.
- instead of the more natural sounding CIRCLE. So with user-defined identifier
- subtypes we have a tradeoff; we need unique identifier names both for our subtype
- identifiers and the v-type for our subtype identifiers so as not to conflict
- with others who might be using identifier subtypes, but those unique names
- might make using macros less "natural" On the other hand, just registering/pre-detecting
- identifiers has no such problem. This is an issue of which any user, looking
- to create his own data type using VMD by defining user-defined subtypes, should
- be aware.
- </p>
- </div>
- <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
- <td align="left"></td>
- <td align="right"><div class="copyright-footer">Copyright © 2010-2017 Tropic Software
- East Inc</div></td>
- </tr></table>
- <hr>
- <div class="spirit-nav">
- <a accesskey="p" href="vmd_modifiers/vmd_modifiers_single.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="vmd_useful.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
- </div>
- </body>
- </html>
|