323 lines
13 KiB
Plaintext
323 lines
13 KiB
Plaintext
[/
|
|
(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]
|