123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- [/
- (C) Copyright Edward Diener 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_empty_ppdata Functionality for "empty" seqs and tuples]
- Boost PP arrays and lists can be empty but seqs and tuples cannot.
- The form of an empty array is '(0,())' and the form of an empty
- list is 'BOOST_PP_NIL'. But the form of '()' does not represent
- an empty seq or an empty tuple. Instead for a seq it represents
- a one element seq whose data is empty, while for a tuple it
- represents a tuple with a size of 1 whose single element is empty.
- Not having a way to represent an empty seq or tuple represents a
- small problem for Boost PP users. For a tuple, especially, not being
- able to be "empty" is the only reason, when variadic macros are supported,
- why an end-user might prefer to use an array rather than a tuple as
- Boost PP preprocessor data. Otherwise, when using variadic macros, using
- a tuple is easier to notate and subsequently use than an array
- since no effort is needed to specify the number of elements of a tuple.
- VMD as we have seen has functionality to tell when preprocessor data is "empty"
- through its BOOST_VMD_IS_EMPTY macro. Because of this it is possible to treat
- emptiness, when applied to a seq or tuple, as an empty seq or an empty tuple
- respectively, thus allowing seqs and tuples to be empty, just as arrays and
- lists are.
- However there is one large problem when treating emptiness as an empty seq or
- empty tuple; Boost PP functionality for a seq or tuple knows nothing about it.
- In other words if you passed emptiness to a Boost PP macro which expects a
- seq or tuple, such as:
- BOOST_PP_SEQ_SIZE()
-
- or
- BOOST_PP_TUPLE_PUSH_BACK(,1)
-
- you would get UB, undefined behavior.
- In order to use seqs and tuples which can be empty VMD defines a number
- of macros which mimic many of those in Boost PP, but begin with BOOST_VMD_
- rather than BOOST_PP_. The VMD macros work with what I will call a 'VMD seq' or
- a 'VMD tuple', while the Boost PP equivalents work with the traditional seq
- or tuple. A VMD seq is a seq which may be empty and a VMD tuple is a tuple
- which may be empty. A VMD seq is therefore a superset of a normal seq and a
- VMD tuple is therefore a superset of a normal tuple. The VMD functionality
- therefore can accept a VMD seq or tuple or a normal seq or tuple whereas the
- equivalent Boost PP functionality only accepts a normal seq or tuple. To be more
- more precise the Boost PP functionality can accept a VMD seq or a VMD tuple as
- long as it is not empty. In other words there is no difference between a
- non-empty VMD seq or a Boost PP seq, or between a non-empty VMD tuple and
- a Boost PP tuple.
- The particular macros which VMD supplies, supporting VMD seqs and VMD tuples,
- are divided between array, list, seq, and tuple functionality. The actual header
- files for these macros are in sub-directories of the VMD directory, which start
- respectively with 'array','list','seq' and 'tuple'. The header files are all
- also included in the general boost/vmd/vmd.hpp header file.
- [heading Array macros]
- The array macros provide conversions from an array to a VMD seq or a VMD tuple.
- The array macros are:
- [table:vpp_array Array macros
- [[Macro][Parameter][Return][Functionality][Header]]
- [
- [BOOST_VMD_ARRAY_TO_SEQ]
- [array = a Boost PP array]
- [A VMD seq]
- [Converts an array to a VMD seq. If the array is empty the seq is empty, otherwise the conversion is the same as BOOST_PP_ARRAY_TO_SEQ]
- [boost/vmd/array/to_seq.hpp]
- ]
- [
- [BOOST_VMD_ARRAY_TO_TUPLE]
- [array = a Boost PP array]
- [A VMD tuple]
- [Converts an array to a VMD tuple. If the array is empty the tuple is empty, otherwise the conversion is the same as BOOST_PP_ARRAY_TO_TUPLE]
- [boost/vmd/array/to_tuple.hpp]
- ]
- ]
- The difference between the array conversion macros and their equivalent ones
- in Boost PP is that if the array is empty the VMD macros return emptiness
- whereas the Boost PP macros have UB.
- You can include the array macros either using their individual header files,
- the general 'boost/vmd/array.hpp' header file for all array macros, or the
- general header file 'boost/vmd/vmd.hpp' for all macros.
- [heading List macros]
- The list macros provide conversions from a list to a VMD seq or a VMD tuple.
- The list macros are:
- [table:vpp_list List macros
- [[Macro][Parameter][Return][Functionality][Header]]
- [
- [BOOST_VMD_LIST_TO_SEQ]
- [list = a Boost PP list]
- [A VMD seq]
- [Converts a list to a VMD seq. If the list is empty the seq is empty, otherwise the conversion is the same as BOOST_PP_LIST_TO_SEQ]
- [boost/vmd/list/to_seq.hpp]
- ]
- [
- [BOOST_VMD_LIST_TO_TUPLE]
- [list = a Boost PP list]
- [A VMD tuple]
- [Converts a list to a VMD tuple. If the list is empty the tuple is empty, otherwise the conversion is the same as BOOST_PP_LIST_TO_TUPLE]
- [boost/vmd/list/to_tuple.hpp]
- ]
- ]
- The difference between the list conversion macros and their equivalent ones
- in Boost PP is that if the list is empty the VMD macros return emptiness
- whereas the Boost PP macros have UB.
- You can include the list macros either using their individual header files,
- the general 'boost/vmd/list.hpp' header file for all list macros, or the
- general header file 'boost/vmd/vmd.hpp' for all macros.
- [heading Seq macros]
- The seq macros either work with a VMD seq or return A VMD seq. The seq macros are:
- [table:vpp_seq Seq macros
- [[Macro][Parameter][Return][Functionality][Header]]
- [
- [BOOST_VMD_IS_VMD_SEQ]
- [sequence = a VMD sequence]
- [1 if the VMD sequence is a VMD seq, else 0]
- [Tests a sequence as a VMD seq. If the sequence is empty returns 1, otherwise returns the same as BOOST_VMD_IS_SEQ]
- [boost/vmd/seq/is_vmd_seq.hpp]
- ]
- [
- [BOOST_VMD_SEQ_POP_BACK]
- [seq = a Boost PP seq]
- [A VMD seq]
- [Pops an element from the end of a seq. If the seq has a single element returns an empty seq, otherwise works exactly the same as BOOST_PP_SEQ_POP_BACK]
- [boost/vmd/seq/pop_back.hpp]
- ]
- [
- [BOOST_VMD_SEQ_POP_FRONT]
- [seq = a Boost PP seq]
- [A VMD seq]
- [Pops an element from the beginning of a seq. If the seq has a single element returns an empty seq, otherwise works exactly the same as BOOST_PP_SEQ_POP_FRONT]
- [boost/vmd/seq/pop_front.hpp]
- ]
- [
- [BOOST_VMD_SEQ_PUSH_BACK]
- [seq = a VMD seq, elem = element to push onto the end of the VMD seq]
- [A Boost PP seq]
- [Pushes an element onto the end of a VMD seq. If the VMD seq is empty the returned seq consists of that element, otherwise works exactly the same as BOOST_PP_SEQ_PUSH_BACK]
- [boost/vmd/seq/push_back.hpp]
- ]
- [
- [BOOST_VMD_SEQ_PUSH_FRONT]
- [seq = a VMD seq, elem = element to push onto the beginning of the VMD seq]
- [A Boost PP seq]
- [Pushes an element onto the beginning of a VMD seq. If the VMD seq is empty the returned seq consists of that element, otherwise works exactly the same as BOOST_PP_SEQ_PUSH_FRONT]
- [boost/vmd/seq/push_front.hpp]
- ]
- [
- [BOOST_VMD_SEQ_REMOVE]
- [seq = a Boost PP seq, i = index of element to remove]
- [A VMD seq]
- [Removes an element from a Boost PP seq. If the seq has a single element and the index to be removed is 0 returns an empty seq, otherwise works exactly the same as BOOST_PP_SEQ_REMOVE]
- [boost/vmd/seq/remove.hpp]
- ]
- [
- [BOOST_VMD_SEQ_SIZE]
- [seq = a VMD seq]
- [The number of elements in the VMD seq]
- [Returns the number of elements in the VMD seq. If the seq is empty returns 0, otherwise works exactly the same as BOOST_PP_SEQ_SIZE]
- [boost/vmd/seq/size.hpp]
- ]
- [
- [BOOST_VMD_SEQ_TO_ARRAY]
- [seq = a VMD seq]
- [A Boost PP array]
- [Converts a VMD seq to a Boost PP array. If the seq is empty returns an empty array whose form is '(0,())', otherwise works exactly the same as BOOST_PP_SEQ_TO_ARRAY]
- [boost/vmd/seq/to_array.hpp]
- ]
- [
- [BOOST_VMD_SEQ_TO_LIST]
- [seq = a VMD seq]
- [A Boost PP list]
- [Converts a VMD seq to a Boost PP list. If the seq is empty returns an empty list whose form is 'BOOST_PP_NIL', otherwise works exactly the same as BOOST_PP_SEQ_TO_LIST]
- [boost/vmd/seq/to_list.hpp]
- ]
- [
- [BOOST_VMD_SEQ_TO_TUPLE]
- [seq = a VMD seq]
- [A VMD tuple]
- [Converts a VMD seq to a VMD tuple. If the seq is empty returns an empty tuple, otherwise works exactly the same as BOOST_PP_SEQ_TO_TUPLE]
- [boost/vmd/seq/to_tuple.hpp]
- ]
- ]
- The difference between the seq macros and their equivalent ones in Boost PP is
- that working with a VMD seq or returning a VMD seq is valid with the seq macros
- but with the Boost PP equivalent macros working with an empty seq causes UB and
- returning an empty seq can never occur.
- You can include the seq macros either using their individual header files,
- the general 'boost/vmd/seq.hpp' header file for all seq macros, or the
- general header file 'boost/vmd/vmd.hpp' for all macros.
- [heading Tuple macros]
- The tuple macros either work with a VMD tuple or return a VMD tuple. The tuple macros are:
- [table:vpp_tuple Tuple macros
- [[Macro][Parameter][Return][Functionality][Header]]
- [
- [BOOST_VMD_IS_VMD_TUPLE]
- [sequence = a VMD sequence]
- [1 if the VMD sequence is a VMD tuple, else 0]
- [Tests a sequence as a VMD tuple. If the sequence is empty returns 1, otherwise returns the same as BOOST_VMD_IS_TUPLE]
- [boost/vmd/tuple/is_vmd_tuple.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_POP_BACK]
- [tuple = a Boost PP tuple]
- [A VMD tuple]
- [Pops an element from the end of a tuple. If the tuple's size is 1 returns an empty tuple, otherwise works exactly the same as BOOST_PP_TUPLE_POP_BACK]
- [boost/vmd/tuple/pop_back.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_POP_FRONT]
- [tuple = a Boost PP tuple]
- [A VMD tuple]
- [Pops an element from the beginning of a tuple. If the tuple's size is 1 returns an empty tuple, otherwise works exactly the same as BOOST_PP_TUPLE_POP_FRONT]
- [boost/vmd/tuple/pop_front.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_PUSH_BACK]
- [tuple = a VMD tuple, elem = element to push onto the end of the VMD tuple]
- [A Boost PP tuple]
- [Pushes an element onto the end of a VMD tuple. If the VMD tuple is empty the returned tuple consists of that element, otherwise works exactly the same as BOOST_PP_TUPLE_PUSH_BACK]
- [boost/vmd/tuple/push_back.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_PUSH_FRONT]
- [tuple = a VMD tuple, elem = element to push onto the beginning of the VMD tuple]
- [A Boost PP tuple]
- [Pushes an element onto the beginning of a VMD tuple. If the VMD tuple is empty the returned tuple consists of that element, otherwise works exactly the same as BOOST_PP_TUPLE_PUSH_FRONT]
- [boost/vmd/tuple/push_front.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_REMOVE]
- [tuple = a Boost PP tuple, i = index of element to remove]
- [A VMD tuple]
- [Removes an element from a Boost PP tuple. If the tuple has a single element and the index to be removed is 0 returns an empty tuple, otherwise works exactly the same as BOOST_PP_TUPLE_REMOVE]
- [boost/vmd/tuple/remove.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_SIZE]
- [tuple = a VMD tuple]
- [The number of elements in the VMD tuple]
- [Returns the number of elements in the VMD tuple. If the tuple is empty returns 0, otherwise works exactly the same as BOOST_PP_TUPLE_SIZE]
- [boost/vmd/tuple/size.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_TO_ARRAY]
- [tuple = a VMD tuple]
- [A Boost PP array]
- [Converts a VMD tuple to a Boost PP array. If the tuple is empty returns an empty array whose form is '(0,())', otherwise works exactly the same as BOOST_PP_TUPLE_TO_ARRAY]
- [boost/vmd/tuple/to_array.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_TO_LIST]
- [tuple = a VMD tuple]
- [A Boost PP list]
- [Converts a VMD tuple to a Boost PP list. If the tuple is empty returns an empty list whose form is 'BOOST_PP_NIL', otherwise works exactly the same as BOOST_PP_TUPLE_TO_LIST]
- [boost/vmd/tuple/to_list.hpp]
- ]
- [
- [BOOST_VMD_TUPLE_TO_SEQ]
- [tuple = a VMD tuple]
- [A VMD seq]
- [Converts a VMD tuple to a VMD seq. If the tuple is empty returns an empty seq, otherwise works exactly the same as BOOST_PP_TUPLE_TO_SEQ]
- [boost/vmd/tuple/to_seq.hpp]
- ]
- ]
- The difference between the tuple macros and their equivalent ones in Boost PP is
- that working with a VMD tuple or returning a VMD tuple is valid with the tuple macros
- but with the Boost PP equivalent macros working with an empty tuple causes UB and
- returning an empty tuple can never occur.
- You can include the tuple macros either using their individual header files,
- the general 'boost/vmd/tuple.hpp' header file for all tuple macros, or the
- general header file 'boost/vmd/vmd.hpp' for all macros.
- [heading Seq and tuple functionality]
- The set of macros for seq and tuple functionality which work with VMD seqs and
- VMD tuples are largely only a subset of the seq and tuple functionality in Boost PP. This reflects
- the fact that a number of macros in Boost PP for working with a seq or tuple make no
- sense when extended to work with a possible empty seq or empty tuple. For instance
- BOOST_PP_SEQ_FIRST_N could not mean anything when passed an empty
- seq and BOOST_PP_TUPLE_REM_CTOR could not mean anything when passed an empty tuple.
- Likewise for other Boost PP seq and tuple macros which do not have a VMD equivalent.
- The set of functionality in VMD for working with a possibly empty seq or empty tuple makes
- it possible to add or remove elements in a seq or tuple which could start out or
- end up empty, take the seq or tuple size even when the seq or tuple is empty,
- convert between arrays, lists, seqs, or tuples which could start out or end up
- empty, and test for a VMD seq or a VMD tuple. This functionality should allow macro
- programmers the ability to work with empty seqs and tuples while still using other
- Boost PP seq and tuple functuionality to work with non-empty seqs and tuples. The
- easiest way to do this is to use the VMD seq and VMD tuple equivalent functions
- when choosing between VMD and Boost PP, and use the Boost PP seq and tuple
- functionality otherwise. Just remember that Boost PP seq and tuple functionality
- can never work with empty seqs or empty tuples.
- [endsect]
|