123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- [/
- (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_modifiers_return_type Return type modifiers]
- A number of macros are capable of returning the type of
- data as a v-type rather than, or along with, the
- data itself. The most obvious of these is BOOST_VMD_GET_TYPE
- which generically returns the type of the input.
- Return type modifiers turn on, turn off, or change
- the type of the data returned in some way.
- These modifiers are:
- * BOOST_VMD_RETURN_NO_TYPE, do not return the type of data.
- * BOOST_VMD_RETURN_TYPE, return the type of data parsing any tuple-like
- syntactical construct as its most specific type. This means that any
- tuple-like construct is parsed first as a possible list, next as a
- possible array if it is not a list, and finally as a tuple if it is not a
- list or an array.
- * BOOST_VMD_RETURN_TYPE_LIST, parse any tuple-like syntactical construct
- first as a possible list and only then as a tuple if it is not a list.
- * BOOST_VMD_RETURN_TYPE_ARRAY, parse any tuple-like syntactical construct
- first as a possible array and only then as a tuple if it is not an array.
- * BOOST_VMD_RETURN_TYPE_TUPLE, parse any tuple-like syntactical construct
- only as a tuple.
- When VMD parses input generically it must determine the type of each data
- element of the input. For nearly all of the VMD data types this is never
- a problem. For the array or list data types this can be a problem, as
- explained when discussing parsing arrays and lists respectively using the
- specific macros BOOST_VMD_IS_ARRAY and BOOST_VMD_IS_LIST. The problem is
- that a valid tuple can be an invalid list or an invalid array, whose
- parsing as the more specific type will lead to UB.
- Because of this when VMD parses input generically,
- and only the data of an element is needed to continue parsing correctly,
- it parses all tuple-like data as a tuple and never as a list or an array.
- When VMD parses input generically, and the type of the data is required
- in some way as part of the return of a macro, VMD by default parses for
- the most specific type of each data element in order to return the most
- accurate type. In this situation by default the
- BOOST_VMD_RETURN_TYPE modifier is internally in effect without having
- to be specified.
- If more than one of the return type modifiers are specified as optional
- parameters the last one specified is in effect.
- [heading Usage with BOOST_VMD_GET_TYPE]
- The only macro in which VMD without the use of modifiers is being asked
- to return the type of data is BOOST_VMD_GET_TYPE. For this macro
- the BOOST_VMD_RETURN_TYPE modifier is internally in effect so if
- no return type modifiers are input as optional parameters BOOST_VMD_GET_TYPE
- looks for the most specific type.
- For the BOOST_VMD_GET_TYPE macro the optional return type modifier
- BOOST_VMD_RETURN_NO_TYPE, if specified, is always ignored since the purpose of
- BOOST_VMD_GET_TYPE is solely to return the v-type.
- Let's look at how this works with BOOST_VMD_GET_TYPE by specifying VMD sequences
- that have tuples which may or may not be valid lists or arrays.
- #include <boost/vmd/get_type.hpp>
-
- #define TUPLE_IS_ARRAY (2,(3,4))
- #define TUPLE_IS_LIST (anydata,BOOST_PP_NIL)
- #define TUPLE_IS_LIST_OR_ARRAY (2,(3,BOOST_PP_NIL))
- #define TUPLE_BUT_INVALID_ARRAY (&2,(3,4))
- #define TUPLE_BUT_INVALID_LIST (anydata,^BOOST_PP_NIL)
- #define SEQUENCE_EMPTY
- #define SEQUENCE_MULTI TUPLE_BUT_INVALID_ARRAY TUPLE_BUT_INVALID_LIST
- BOOST_VMD_GET_TYPE(TUPLE_IS_ARRAY) will return BOOST_VMD_TYPE_ARRAY, the most specific type
- BOOST_VMD_GET_TYPE(TUPLE_IS_ARRAY,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
- BOOST_VMD_GET_TYPE(TUPLE_IS_ARRAY,BOOST_VMD_RETURN_TYPE_ARRAY) will return BOOST_VMD_TYPE_ARRAY
- BOOST_VMD_GET_TYPE(TUPLE_IS_ARRAY,BOOST_VMD_RETURN_TYPE_LIST) will return BOOST_VMD_TYPE_TUPLE
-
- BOOST_VMD_GET_TYPE(TUPLE_IS_LIST) will return BOOST_VMD_TYPE_LIST, the most specific type
- BOOST_VMD_GET_TYPE(TUPLE_IS_LIST,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
- BOOST_VMD_GET_TYPE(TUPLE_IS_LIST,BOOST_VMD_RETURN_TYPE_ARRAY) will return BOOST_VMD_TYPE_TUPLE
- BOOST_VMD_GET_TYPE(TUPLE_IS_LIST,BOOST_VMD_RETURN_TYPE_LIST) will return BOOST_VMD_TYPE_LIST
-
- BOOST_VMD_GET_TYPE(TUPLE_IS_LIST_OR_ARRAY) will return BOOST_VMD_TYPE_LIST, the most specific type
- BOOST_VMD_GET_TYPE(TUPLE_IS_LIST_OR_ARRAY,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
- BOOST_VMD_GET_TYPE(TUPLE_IS_LIST_OR_ARRAY,BOOST_VMD_RETURN_TYPE_ARRAY) will return BOOST_VMD_TYPE_ARRAY
- BOOST_VMD_GET_TYPE(TUPLE_IS_LIST_OR_ARRAY,BOOST_VMD_RETURN_TYPE_LIST) will return BOOST_VMD_TYPE_LIST
-
- BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_ARRAY) will give UB
- BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_ARRAY,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
- BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_ARRAY,BOOST_VMD_RETURN_TYPE_ARRAY) will give UB
- BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_ARRAY,BOOST_VMD_RETURN_TYPE_LIST) will return BOOST_VMD_TYPE_TUPLE
-
- BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_LIST) will give UB
- BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_LIST,BOOST_VMD_RETURN_TYPE_TUPLE) will return BOOST_VMD_TYPE_TUPLE
- BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_LIST,BOOST_VMD_RETURN_TYPE_ARRAY) will return BOOST_VMD_TYPE_TUPLE
- BOOST_VMD_GET_TYPE(TUPLE_BUT_INVALID_LIST,BOOST_VMD_RETURN_TYPE_LIST) will give UB
-
- BOOST_VMD_GET_TYPE(SEQUENCE_EMPTY)
- will always return BOOST_VMD_TYPE_EMPTY even if we add any return type modifiers
- BOOST_VMD_GET_TYPE(SEQUENCE_MULTI)
- will always return BOOST_VMD_TYPE_SEQUENCE even if we add any return type modifiers
- [heading Usage with sequence converting macros]
- The sequence converting macros converts a sequence to a composite Boost PP data type
- or to variadic data, where each element's data in the sequence becomes an element in the
- destination composite type. The macros are:
- * BOOST_VMD_TO_ARRAY, converts the sequence to an array
- * BOOST_VMD_TO_LIST, converts the sequence to a list
- * BOOST_VMD_TO_SEQ, converts the sequence to a seq
- * BOOST_VMD_TO_TUPLE, converts the sequence to a tuple
- * BOOST_VMD_ENUM, converts the sequence to variadic data
- When it does the conversion, using just the required parameter of the sequence itself,
- it converts only the data value of each sequence element to the
- elements of a composite Boost PP data type or variadic data. Because it needs only the data
- value of each sequence element it determines the type of each sequence element as
- the most general type that it can be. This means that all tuple-like data are parsed as
- tuples rather than as possible lists or arrays.
- Using a return type modifier we can convert from a VMD sequence to a
- Boost PP composite data type or variadic data and retain the type of data of each
- element in the sequence as part of the conversion. When doing this each of the
- converted elements of the composite data type becomes a two-element tuple where
- the first element is the type of the data and the second element is the data itself.
- For the sequence conversion macros the default return type modifier internally set is
- BOOST_VMD_RETURN_NO_TYPE, which means that the type is not retained.
- By specifying another optional return type modifier
- we tell the conversion to preserve the type in the conversion output.
- If the sequence is empty, since there are no sequence elements,
- any return type modifier we use accomplishes nothing but is fine to use.
- First we show how sequence conversion macros work with the BOOST_VMD_RETURN_TYPE
- modifier, which always parses for the most specific type.
- #include <boost/vmd/enum.hpp>
- #include <boost/vmd/to_array.hpp>
- #include <boost/vmd/to_list.hpp>
- #include <boost/vmd/to_seq.hpp>
- #include <boost/vmd/to_tuple.hpp>
-
- #define BOOST_VMD_REGISTER_ANID (ANID)
- #define SEQUENCE_EMPTY_1
- #define SEQUENCE_SINGLE 35
- #define SEQUENCE_SINGLE_ID ANID
- #define SEQUENCE_SINGLE_ARRAY (3,(0,1,2))
- #define SEQUENCE_SINGLE_LIST (data,(more_data,BOOST_PP_NIL))
- #define SEQUENCE_MULTI_1 (0,1) (2)(3)(4)
- #define SEQUENCE_MULTI_2 BOOST_VMD_TYPE_SEQ (2,(5,6))
-
- BOOST_VMD_TO_ARRAY(SEQUENCE_EMPTY_1) will return an empty array '(0,())'
- BOOST_VMD_TO_ARRAY(SEQUENCE_EMPTY_1,BOOST_VMD_RETURN_TYPE) will return an empty array '(0,())'
-
- BOOST_VMD_TO_LIST(SEQUENCE_SINGLE) will return a one-element list '(35,BOOST_PP_NIL)'
- BOOST_VMD_TO_LIST(SEQUENCE_SINGLE,BOOST_VMD_RETURN_TYPE)
- will return a one-element list '((BOOST_VMD_TYPE_NUMBER,35),BOOST_PP_NIL)'
-
- BOOST_VMD_TO_SEQ(SEQUENCE_SINGLE_ID) will return a one-element seq '(ANID)'
- BOOST_VMD_TO_SEQ(SEQUENCE_SINGLE_ID,BOOST_VMD_RETURN_TYPE)
- will return a one-element seq '((BOOST_VMD_TYPE_IDENTIFIER,ANID))'
-
- BOOST_VMD_TO_TUPLE(SEQUENCE_SINGLE_ARRAY) will return a single element tuple '((3,(0,1,2)))'
- BOOST_VMD_TO_TUPLE(SEQUENCE_SINGLE_ARRAY,BOOST_VMD_RETURN_TYPE)
- will return a single element tuple '((BOOST_VMD_TYPE_ARRAY,(3,(0,1,2))))'
-
- BOOST_VMD_ENUM(SEQUENCE_SINGLE_LIST) will return the single-element '(data,(more_data,BOOST_PP_NIL))'
- BOOST_VMD_ENUM(SEQUENCE_SINGLE_LIST,BOOST_VMD_RETURN_TYPE)
- will return the single element '(BOOST_VMD_TYPE_LIST,(data,(more_data,BOOST_PP_NIL)))'
-
- BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_1) will return a multi-element tuple '((0,1),(2)(3)(4))'
- BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_1,BOOST_VMD_RETURN_TYPE)
- will return a multi-element tuple '((BOOST_VMD_TYPE_TUPLE,(0,1)),(BOOST_VMD_TYPE_SEQ,(2)(3)(4)))'
-
- BOOST_VMD_ENUM(SEQUENCE_MULTI_2) will return multi-element variadic data 'BOOST_VMD_TYPE_SEQ,(2,(5,6))'
- BOOST_VMD_ENUM(SEQUENCE_MULTI_2,BOOST_VMD_RETURN_TYPE)
- will return multi-element variadic data '(BOOST_VMD_TYPE_TYPE,BOOST_VMD_TYPE_SEQ),(BOOST_VMD_TYPE_ARRAY,(2,(5,6)))'
-
- Lets look at how we might use other return type modifiers when doing conversions
- to avoid UB if we want the type as part of the conversion but
- the type might be a valid tuple while being an invalid list or array.
- #define TUPLE_IS_VALID_ARRAY (2,(3,4))
- #define TUPLE_IS_VALID_LIST (anydata,BOOST_PP_NIL)
- #define TUPLE_BUT_INVALID_ARRAY_2 (&2,(3,4))
- #define TUPLE_BUT_INVALID_LIST_2 (anydata,^BOOST_PP_NIL)
-
- #define SEQUENCE_MULTI_T1 TUPLE_IS_VALID_ARRAY TUPLE_IS_VALID_LIST
- #define SEQUENCE_MULTI_T2 TUPLE_BUT_INVALID_ARRAY_2 TUPLE_IS_VALID_LIST
- #define SEQUENCE_MULTI_T3 TUPLE_IS_VALID_ARRAY TUPLE_BUT_INVALID_LIST_2
- #define SEQUENCE_MULTI_T4 TUPLE_BUT_INVALID_ARRAY_2 TUPLE_BUT_INVALID_LIST_2
-
- We present a number of uses of various sequence conversions
- with each of our four different sequences, and show their results.
-
- #include <boost/vmd/to_seq.hpp>
-
- BOOST_VMD_TO_SEQ(SEQUENCE_MULTI_T1,BOOST_VMD_RETURN_TYPE)
- will return the seq '((BOOST_VMD_TYPE_ARRAY,(2,(3,4)))) ((BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'
- BOOST_VMD_TO_SEQ(SEQUENCE_MULTI_T1,BOOST_VMD_RETURN_TYPE_ARRAY)
- will return the seq '((BOOST_VMD_TYPE_ARRAY,(2,(3,4)))) ((BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'
- BOOST_VMD_TO_SEQ(SEQUENCE_MULTI_T1,BOOST_VMD_RETURN_TYPE_LIST)
- will return the seq '((BOOST_VMD_TYPE_TUPLE,(2,(3,4)))) ((BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'
- BOOST_VMD_TO_SEQ(SEQUENCE_MULTI_T1,BOOST_VMD_RETURN_TYPE_TUPLE)
- will return the seq '((BOOST_VMD_TYPE_TUPLE,(2,(3,4)))) ((BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'
-
- The SEQUENCE_MULTI_T1 is a valid array followed by a valid list. All return type
- modifiers produce their results without any UBs.
- #include <boost/vmd/to_tuple.hpp>
-
- BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_T2,BOOST_VMD_RETURN_TYPE)
- will produce UB when attempting to parse the invalid array as an array
- BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_T2,BOOST_VMD_RETURN_TYPE_ARRAY)
- will produce UB when attempting to parse the invalid array as an array
- BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_T2,BOOST_VMD_RETURN_TYPE_LIST)
- will return the tuple '((BOOST_VMD_TYPE_TUPLE,(&2,(3,4))),(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL)))'
- BOOST_VMD_TO_TUPLE(SEQUENCE_MULTI_T2,BOOST_VMD_RETURN_TYPE_TUPLE)
- will return the tuple '((BOOST_VMD_TYPE_TUPLE,(&2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL)))'
-
- The SEQUENCE_MULTI_T2 is an invalid array, but valid tuple, followed by a valid list.
- In sequence conversion we will get UB whenever we use a return type
- modifier that parses the data type of the invalid array as an array. But if we use
- the return type modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE
- we are never parsing the invalid array as an array but as a tuple instead and therefore
- we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
- #include <boost/vmd/to_array.hpp>
-
- BOOST_VMD_TO_ARRAY(SEQUENCE_MULTI_T3,BOOST_VMD_RETURN_TYPE)
- will produce UB when attempting to parse the invalid list as a list
- BOOST_VMD_TO_ARRAY(SEQUENCE_MULTI_T3,BOOST_VMD_RETURN_TYPE_LIST)
- will produce UB when attempting to parse the invalid list as a list
- BOOST_VMD_TO_ARRAY(SEQUENCE_MULTI_T3,BOOST_VMD_RETURN_TYPE_ARRAY)
- will return the array '(2,((BOOST_VMD_TYPE_ARRAY,(2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL))))'
- BOOST_VMD_TO_ARRAY(SEQUENCE_MULTI_T3,BOOST_VMD_RETURN_TYPE_TUPLE)
- will return the array '(2,((BOOST_VMD_TYPE_TUPLE,(2,(3,4))),(BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL))))'
-
- The SEQUENCE_MULTI_T3 is a valid array followed by an invalid list, but a valid tuple.
- In sequence conversion we will get UBs whenever we use a return type
- modifier that parses the data type of the invalid list as a list. But if we use
- the return type modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE
- we are never parsing the invalid list as a list but as a tuple instead and therefore
- we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
- #include <boost/vmd/to_list.hpp>
-
- BOOST_VMD_TO_LIST(SEQUENCE_MULTI_T4,BOOST_VMD_RETURN_TYPE)
- will produce UB when attempting to parse the invalid array or invalid list
- BOOST_VMD_TO_LIST(SEQUENCE_MULTI_T4,BOOST_VMD_RETURN_TYPE_ARRAY)
- will produce UB when attempting to parse the invalid array
- BOOST_VMD_TO_LIST(SEQUENCE_MULTI_T4,BOOST_VMD_RETURN_TYPE_LIST)
- will produce UB when attempting to parse the invalid list
- BOOST_VMD_TO_LIST(SEQUENCE_MULTI_T4,BOOST_VMD_RETURN_TYPE_TUPLE)
- will return the list '((BOOST_VMD_TYPE_TUPLE,(&2,(3,4))),((BOOST_VMD_TYPE_TUPLE,(anydata,^BOOST_PP_NIL)),BOOST_PP_NIL))'
-
- The SEQUENCE_MULTI_T4 is an invalid array, but valid tuple, followed by an invalid list, but valid tuple.
- In sequence conversion we will get UBs whenever we use a return type
- modifier that parses the sequence other than looking for only valid tuples. So here we must use
- the return type modifier BOOST_VMD_RETURN_TYPE_TUPLE for a sequence conversion without
- generating UBs.
-
- [heading Usage with BOOST_VMD_ELEM]
- The default functionality of BOOST_VMD_ELEM when the required parameters are used
- is to return the particular element's data. When BOOST_VMD_ELEM does this it parses
- all elements of the sequence by determining the most general type of data for each
- element. The parsing algorithm stops when it reaches the element number whose data
- is returned. This means that all tuple-like data are parsed as tuples rather than
- as possible lists or arrays.
- Using return type modifiers as optional parameters we can tell BOOST_VMD_ELEM to
- return the type of the element found, as well as its data, in the form of a two
- element tuple. The first element of the tuple is the type of the data and the
- second element of the tuple is the data itself.
- When we use a return type modifier with BOOST_VMD_ELEM, which tells us to return
- the type of the data along with the data, the particular modifier only tells
- BOOST_VMD_ELEM how to parse the type of data for the element found.
- BOOST_VMD_ELEM will continue to parse elements in the sequence preceding the
- element found by determining the most general type of the data since this is
- the safest way of parsing the data itself.
- Using the return type modifier BOOST_VMD_RETURN_TYPE with BOOST_VMD_ELEM is
- perfectly safe as long as the particular element found is not an invalid list
- or array, but a valid tuple. It is when the element found may be an invalid
- list or invalid array that we must use other return type modifiers in order
- to parse the type of the element correctly.
- #include <boost/vmd/elem.hpp>
-
- #define BOOST_VMD_REGISTER_ANID_E (ANID_E)
- #define SEQUENCE_SINGLE_E 35
- #define SEQUENCE_SINGLE_E2 ANID_E
- #define SEQUENCE_MULTI_E (0,1) (2)(3)(4)
- #define SEQUENCE_MULTI_E_2 BOOST_VMD_TYPE_SEQ (2,(5,6))
-
- BOOST_VMD_ELEM(0,SEQUENCE_SINGLE_E) will return '35'
- BOOST_VMD_ELEM(0,SEQUENCE_SINGLE_E,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_NUMBER,35)'
- BOOST_VMD_ELEM(0,SEQUENCE_SINGLE_E2) will return 'ANID_E'
- BOOST_VMD_ELEM(0,SEQUENCE_SINGLE_E2,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_IDENTIFIER,ANID_E)'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E) will return '(2)(3)(4)'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_SEQ,(2)(3)(4))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E_2) will return 'BOOST_VMD_TYPE_SEQ'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E_2,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_TYPE,BOOST_VMD_TYPE_SEQ)'
- When we use the other return type modifiers with BOOST_VMD_ELEM we do so
- because the element we want may be an invalid list or an invalid array
- but a valid tuple and yet we still want its type returned as part of the result.
- Let's look at how this works with BOOST_VMD_ELEM by specifying VMD sequences
- that have tuples which are in the form of arrays or lists which cannot be
- parsed as such by VMD without generating UBs.
- #define TUPLE_IS_VALID_ARRAY_E (2,(3,4))
- #define TUPLE_IS_VALID_LIST_E (anydata,BOOST_PP_NIL)
- #define TUPLE_BUT_INVALID_ARRAY_E (&2,(3,4))
- #define TUPLE_BUT_INVALID_LIST_E (anydata,^BOOST_PP_NIL)
-
- #define SEQUENCE_MULTI_E1 TUPLE_IS_VALID_ARRAY_E TUPLE_IS_VALID_LIST_E
- #define SEQUENCE_MULTI_E2 TUPLE_BUT_INVALID_ARRAY_E TUPLE_IS_VALID_LIST_E
- #define SEQUENCE_MULTI_E3 TUPLE_IS_VALID_ARRAY_E TUPLE_BUT_INVALID_LIST_E
- #define SEQUENCE_MULTI_E4 TUPLE_BUT_INVALID_ARRAY_E TUPLE_BUT_INVALID_LIST_E
-
- We present a number of uses of BOOST_VMD_ELEM with each of our four
- different sequences, and show their results.
-
- #include <boost/vmd/elem.hpp>
-
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E1,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
-
- The SEQUENCE_MULTI_E1 is a valid array followed by a valid list. All return type
- modifiers produce their results without any UBs.
- #include <boost/vmd/elem.hpp>
-
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE)
- will produce UB when attempting to parse the invalid array as an array
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_ARRAY)
- will produce UB when attempting to parse the invalid array as an array
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_TUPLE,(&2,(3,4)))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(&2,(3,4)))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_LIST,(anydata,BOOST_PP_NIL))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E2,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
-
- The SEQUENCE_MULTI_E2 is an invalid array, but valid tuple, followed by a valid list.
- When we access element 0 of our sequence, and use a return type modifier that parses
- its data type as an array we will get UB. But if we use the return
- type modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE
- we are never parsing the invalid array as an array but as a tuple instead and therefore
- we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
- When we access element 1 of our sequence, which is both a valid list and a valid tuple,
- we will never get UB. We will get the return type of the element based
- on which return type modifier we use.
- #include <boost/vmd/elem.hpp>
-
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE) will return '(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_ARRAY,(2,(3,4)))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE)
- will produce UB when attempting to parse the invalid list as a list
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_LIST)
- will produce UB when attempting to parse the invalid list as a list
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E3,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
-
- The SEQUENCE_MULTI_E3 is a valid array followed by an invalid list, but valid tuple.
- When we access element 0 of our sequence, which is both a valid array and a valid tuple,
- we will never get UB. We will get the return type of the element based
- on which return type modifier we use.
- When we access element 1 of our sequence, and use a return type modifier that parses
- its data type as a list we will get UB. But if we use the return
- type modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE
- we are never parsing the invalid list as a list but as a tuple instead and therefore
- we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
- #include <boost/vmd/elem.hpp>
-
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE)
- will produce UB when attempting to parse the invalid array
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_ARRAY)
- will produce UB when attempting to parse the invalid array
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_LIST) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
- BOOST_VMD_ELEM(0,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(2,(3,4)))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE)
- will produce UB when attempting to parse the invalid list
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_ARRAY) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_LIST)
- will produce UB when attempting to parse the invalid list
- BOOST_VMD_ELEM(1,SEQUENCE_MULTI_E4,BOOST_VMD_RETURN_TYPE_TUPLE) will return '(BOOST_VMD_TYPE_TUPLE,(anydata,BOOST_PP_NIL))'
- The SEQUENCE_MULTI_E4 is an invalid array, but valid tuple, followed by an invalid list, but valid tuple.
- When we access element 0 of our sequence, which is an invalid array but a valid tuple,
- we must use a return type modifier which does not parse element 0 as an array, else
- we will get UB. This means we must use the return
- type modifiers BOOST_VMD_RETURN_TYPE_LIST or BOOST_VMD_RETURN_TYPE_TUPLE so
- we are never parsing the invalid array as an array but as a tuple instead and therefore
- we successfully return the type of the invalid array as a BOOST_VMD_TYPE_TUPLE.
- When we access element 1 of our sequence, which is an invalid list but a valid tuple,
- we must use a return type modifier which does not parse element 1 as a list, else
- we will get UB. This means we must use the return
- type modifiers BOOST_VMD_RETURN_TYPE_ARRAY or BOOST_VMD_RETURN_TYPE_TUPLE so
- we are never parsing the invalid list as a list but as a tuple instead and therefore
- we successfully return the type of the invalid list as a BOOST_VMD_TYPE_TUPLE.
- [heading Usage with other modifiers of BOOST_VMD_ELEM]
- We have not yet discussed the rest of the modifiers which may be
- used with BOOST_VMD_ELEM, but return type modifiers are completely
- independent of any of them. This means they can be combined with
- other modifiers and whenever the element of the sequence is
- returned the return type modifiers determine of what the value of that
- element consists; whether it be just the element data or the element
- as a type/data tuple with the type parsed according to our return type
- modifier. When we subsequently discuss the use of other modifiers with
- BOOST_VMD_ELEM and refer to the element being returned, we are referring
- to that element as it is determined by the return type modifiers, which
- by default only returns the element's data.
- [endsect]
|