123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- [/
- (C) Copyright Edward Diener 2011-2015
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt).
- ]
- [section:vmd_whyhow Why and how to use]
- The VMD library provides the ability to create a macro which takes
- different types of parameters and can therefore generate different output
- depending on the parameter types as well as their values.
- This is equivalent to the way that overloaded
- functions provide the ability for a singularly named function
- to provide different functionality depending on the parameter
- types.
- In the case of macros, where more than one macro of the same
- name but different macro expansion is not allowed, a single macro name
- can create different expansions.
- As a simple example:
- #include <boost/vmd/is_seq.hpp>
- #include <boost/vmd/is_tuple.hpp>
- #define AMACRO(param) \
- BOOST_PP_IIF \
- ( \
- BOOST_VMD_IS_SEQ(param), \
- Seq, \
- BOOST_PP_IIF \
- ( \
- BOOST_VMD_IS_TUPLE(param), \
- Tuple, \
- Unknown \
- ) \
- )
- If the param passed is a seq the output of
- the macro is 'Seq'. If the param passed is
- a tuple the output of the macro is 'Tuple'.
- Otherwise the output of the macro is 'Unknown'.
- Obviously much more complicated cases can be created
- in which the types and values of various parameters
- are parsed in order to produce variable macro output
- depending on the input. Using variadic macros,
- macros with variable numbers and types of arguments
- give the macro programmer even greater freedom to
- design macros with flexibility.
- Another feature of the VMD library is the ability to parse
- identifiers. A system of registering identifiers which VMD
- can recognize has been created. Once an identifier is registered
- VMD can recognize it as part of macro input as an identifier and
- return the identifier. Furthermore VMD can compare identifiers
- for equality or inequality once an identifier has been pre-detected
- using VMD's system for pre-detecting identifiers.
- As another simple example:
- #include <boost/vmd/is_identifier.hpp>
-
- #define BOOST_VMD_REGISTER_NAME (NAME)
- #define BOOST_VMD_REGISTER_ADDRESS (ADDRESS)
-
- #define AMACRO1(param) \
- BOOST_PP_IIF \
- ( \
- BOOST_VMD_IS_IDENTIFIER(param), \
- AMACRO1_IDENTIFIER, \
- AMACRO1_NO_IDENTIFIER \
- ) \
- (param)
-
- #define AMACRO1_IDENTIFIER(param) AMACRO1_ ## param
- #define AMACRO1_NO_IDENTIFIER(param) Parameter is not an identifier
- #define AMACRO1_NAME Identifier is a NAME
- #define AMACRO1_ADDRESS Identifier is an ADDRESS
-
- Here we use VMD's identifier registration system to determine and
- handle a particular identifier we may be expecting as a macro parameter.
- If the input to 'AMACRO1' is 'NAME' the output is 'Identifier is a NAME'.
- If the input to 'AMACRO1' is 'ADDRESS' the output is 'Identifier is an ADDRESS'.
- Otherwise the output is 'Parameter is not an identifier'.
- Identifier pre-detection makes things clearer, allowing us to
- detect within VMD whether macro input matches a particular identifier.
- Using the same setup as our previous example, but with identifier pre-detection:
- #include <boost/vmd/is_identifier.hpp>
-
- #define BOOST_VMD_REGISTER_NAME (NAME)
- #define BOOST_VMD_DETECT_NAME_NAME
-
- #define BOOST_VMD_REGISTER_ADDRESS (ADDRESS)
- #define BOOST_VMD_DETECT_ADDRESS_ADDRESS
-
- #define AMACRO2(param) \
- BOOST_PP_IIF \
- ( \
- BOOST_VMD_IS_IDENTIFIER(param,NAME), \
- AMACRO2_NAME, \
- BOOST_PP_IIF \
- ( \
- BOOST_VMD_IS_IDENTIFIER(param,ADDRESS), \
- AMACRO2_ADDRESS, \
- AMACRO2_NO_IDENTIFIER \
- ) \
- ) \
- (param)
-
- #define AMACRO2_NO_IDENTIFIER(param) Parameter is not a NAME or ADDRESS identifier
- #define AMACRO2_NAME(param) Identifier is a NAME
- #define AMACRO2_ADDRESS(param) Identifier is an ADDRESS
-
- If the input to 'AMACRO2' is 'NAME' the output is 'Identifier is a NAME'.
- If the input to 'AMACRO2' is 'ADDRESS' the output is 'Identifier is an ADDRESS'.
- Otherwise the output is 'Parameter is not a NAME or ADDRESS identifier'.
- The VMD library also has 2 different subtypes of identifiers which can always be
- recognized. The first are numbers, equivalent to the number in Boost PP, numeric
- values with a range of 0-256. The second are v-types, which are identifiers starting
- with BOOST_VMD_TYPE_ followed by a name for the type of data. As an example, the v-type
- of a Boost PP tuple is BOOST_VMD_TYPE_TUPLE and the v-type of a v-type itself is
- BOOST_VMD_TYPE_TYPE. All data types have their own v-type identifier; types are
- recognized by the VMD macros and may be passed as input data just like any other of
- the types of data VMD recognizes.
- The VMD identifier system even has a way, to be explained later, for the end-user to
- create his own subtype identifiers.
- Another reason to use VMD is that VMD understands 'sequences' of the VMD data types. You
- can have a sequence of data types and VMD can convert the sequence to any of the Boost
- PP data types, or access any individual data type in a sequence.
- #include <boost/vmd/elem.hpp>
- #include <boost/vmd/to_tuple.hpp>
-
- #define BOOST_VMD_REGISTER_NAME (NAME)
- #define ASEQUENCE (1,2) NAME 147 BOOST_VMD_TYPE_NUMBER (a)(b)
-
- BOOST_VMD_TO_TUPLE(ASEQUENCE)
- BOOST_VMD_ELEM(2,ASEQUENCE)
-
- Our first expansion returns the tuple:
- ((1,2),NAME,147,BOOST_VMD_TYPE_NUMBER,(a)(b))
- Our second expansion returns the sequence element:
- 147
-
- Sequences give the macro programmer the ability to accept input
- data from the user which may more closely mimic C++ constructs.
- Another reason to use VMD is that VMD understands data types.
- Besides specifically asking if a particular input is a particular
- data type, you can use the macro BOOST_VMD_GET_TYPE to retrieve
- the type of any VMD data.
- #include <boost/vmd/get_type.hpp>
-
- BOOST_VMD_GET_TYPE((1,2)) // expands to BOOST_VMD_TYPE_TUPLE
- BOOST_VMD_GET_TYPE(235) // expands to BOOST_VMD_TYPE_NUMBER
-
- etc.
- There is still much more of VMD functionality but hopefully this brief
- introduction of what VMD can do will interest you so that you will read on
- to understand VMD's functionality for the macro programmer.
- [endsect]
|