...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Filtering modifiers are optional modifiers which work with some generic macros to specify a type of data to apply to the macro's functionality. The filtering modifier itself is an optional parameter specified as a v-type. Any v-type, specified as an optional parameter, may be used as a filtering modifier.
The equality macros, BOOST_VMD_EQUAL and BOOST_VMD_NOT_EQUAL, tests generically whether each of its two required inputs are equal or not equal to each other.
Each of these macro takes a single optional parameter, a filtering modifier, to narrow the focus of its equality testing to a particular v-type.
For the macro BOOST_VMD_EQUAL this optional parameter when specified means that equality is not only that the two required input parameters are equal but also that they are of the type or of a subtype of the third optional parameter. A number and a v-type are subtypes of identifiers while a non-empty list and an array are subtypes of tuples.
Conversely BOOST_VMD_NOT_EQUAL, with the optional third v-type parameter, returns 1 if either the first two parameters are not equal or if the type of the first two parameters is not the type or a subtype of the third parameter. Otherwise it returns 0. It is implemented as the complement of BOOST_VMD_EQUAL so that whenever BOOST_VMD_EQUAL returns 1, BOOST_VMD_NOT_EQUAL returns 0 and vice versa.
Here is an example of using BOOST_VMD_EQUAL with a filtering modifier. BOOST_VMD_NOT_EQUAL is just the complement of the results in our example for each result, and would be redundant to be specified each time below.
#include <boost/vmd/equal.hpp> #define BOOST_VMD_REGISTER_AN_ID1 (AN_ID1) #define BOOST_VMD_REGISTER_AN_ID2 (AN_ID2) #define BOOST_VMD_DETECT_AN_ID1_AN_ID1 #define BOOST_VMD_DETECT_AN_ID2_AN_ID2 #define AN_IDENTIFIER1 AN_ID1 #define AN_IDENTIFIER2 AN_ID2 #define AN_IDENTIFIER3 AN_ID1 // same as AN_IDENTIFIER1 = AN_ID1 #define A_NUMBER1 33 #define A_NUMBER2 145 #define A_NUMBER3 33 // same as A_NUMBER1 = 33 #define A_TUPLE1 (AN_IDENTIFIER1,A_NUMBER1) #define A_TUPLE2 (AN_IDENTIFIER1,A_NUMBER2) #define A_TUPLE3 (AN_IDENTIFIER3,A_NUMBER3) // same as A_TUPLE1 = (AN_ID1,33) #define A_LIST1 (A_NUMBER1,(A_NUMBER3,BOOST_PP_NIL)) #define A_LIST2 (A_NUMBER1,(A_NUMBER2,BOOST_PP_NIL)) #define A_LIST3 (A_NUMBER1,(A_NUMBER3,BOOST_PP_NIL)) #define A_LIST4 BOOST_PP_NIL // empty list #define A_LIST5 BOOST_PP_NIL // empty list BOOST_VMD_EQUAL(AN_IDENTIFIER1,AN_IDENTIFIER2,BOOST_VMD_TYPE_IDENTIFIER) will return 0 BOOST_VMD_EQUAL(AN_IDENTIFIER1,AN_IDENTIFIER3,BOOST_VMD_TYPE_IDENTIFIER) will return 1 BOOST_VMD_EQUAL(AN_IDENTIFIER1,AN_IDENTIFIER3,BOOST_VMD_TYPE_TYPE) will return 0 because the type does not match BOOST_VMD_EQUAL(A_NUMBER1,A_NUMBER2,BOOST_VMD_TYPE_NUMBER) will return 0 BOOST_VMD_EQUAL(A_NUMBER1,A_NUMBER3,BOOST_VMD_TYPE_NUMBER) will return 1 BOOST_VMD_EQUAL(A_NUMBER1,A_NUMBER3,BOOST_VMD_TYPE_IDENTIFIER) will return 1 because a number is an identifier BOOST_VMD_EQUAL(A_NUMBER1,A_NUMBER3,BOOST_VMD_TYPE_EMPTY) will return 0 because the type does not match BOOST_VMD_EQUAL(A_TUPLE1,A_TUPLE2,BOOST_VMD_TYPE_TUPLE) will return 0 BOOST_VMD_EQUAL(A_TUPLE1,A_TUPLE3,BOOST_VMD_TYPE_TUPLE) will return 1 BOOST_VMD_EQUAL(A_TUPLE1,A_TUPLE3,BOOST_VMD_TYPE_ARRAY) will return 0 because the type does not match BOOST_VMD_EQUAL(A_LIST1,A_LIST2,BOOST_VMD_TYPE_LIST) will return 0 BOOST_VMD_EQUAL(A_LIST1,A_LIST3,BOOST_VMD_TYPE_LIST) will return 1 BOOST_VMD_EQUAL(A_LIST1,A_LIST3,BOOST_VMD_TYPE_IDENTIFIER) will return 0 because the type does not match BOOST_VMD_EQUAL(A_LIST1,A_LIST3,BOOST_VMD_TYPE_TUPLE) will return 1 because a non-empty list is also a tuple BOOST_VMD_EQUAL(A_LIST4,A_LIST5,BOOST_VMD_TYPE_LIST) will return 1 BOOST_VMD_EQUAL(A_LIST4,A_LIST5,BOOST_VMD_TYPE_IDENTIFIER) will return 1 because an empty list is also an identifier BOOST_VMD_EQUAL(A_LIST4,A_LIST5,BOOST_VMD_TYPE_TUPLE) will return 0 because an empty list is not a tuple
As with the equality macros BOOST_VMD_ELEM allows one to perform filtering for the result. An optional parameter of a v-type can be used so that BOOST_VMD_ELEM returns its result only if the sequence element is of the v-type specified, else it fails to find the element in the same way that an element number which is outside the bounds of the sequence fails.
#include <boost/vmd/elem.hpp> #define BOOST_VMD_REGISTER_ANAME (ANAME) // an identifier must always be registered to be found by VMD #define A_SEQUENCE (1,2,3) 46 (list_data1,(list_data2,BOOST_PP_NIL)) BOOST_VMD_TYPE_SEQ ANAME BOOST_VMD_ELEM(0,A_SEQUENCE) will return (1,2,3) BOOST_VMD_ELEM(0,A_SEQUENCE,BOOST_VMD_TYPE_TUPLE) will return (1,2,3) BOOST_VMD_ELEM(0,A_SEQUENCE,BOOST_VMD_TYPE_SEQ) will return emptiness BOOST_VMD_ELEM(1,A_SEQUENCE) will return 46 BOOST_VMD_ELEM(1,A_SEQUENCE,BOOST_VMD_TYPE_NUMBER) will return 46 BOOST_VMD_ELEM(1,A_SEQUENCE,BOOST_VMD_TYPE_IDENTIFIER) will return 46 since a number is also an identifier BOOST_VMD_ELEM(1,A_SEQUENCE,BOOST_VMD_TYPE_LIST) will return emptiness BOOST_VMD_ELEM(2,A_SEQUENCE) will return (list_data1,(list_data2,BOOST_PP_NIL)) BOOST_VMD_ELEM(2,A_SEQUENCE,BOOST_VMD_TYPE_LIST) will return (list_data1,(list_data2,BOOST_PP_NIL)) BOOST_VMD_ELEM(2,A_SEQUENCE,BOOST_VMD_TYPE_TUPLE) will return (list_data1,(list_data2,BOOST_PP_NIL)) since a list is also a tuple BOOST_VMD_ELEM(2,A_SEQUENCE,BOOST_VMD_TYPE_TYPE) will return emptiness BOOST_VMD_ELEM(3,A_SEQUENCE) will return BOOST_VMD_TYPE_SEQ BOOST_VMD_ELEM(3,A_SEQUENCE,BOOST_VMD_TYPE_TYPE) will return BOOST_VMD_TYPE_SEQ BOOST_VMD_ELEM(3,A_SEQUENCE,BOOST_VMD_TYPE_IDENTIFIER) will return BOOST_VMD_TYPE_SEQ since a type is also an identifier BOOST_VMD_ELEM(3,A_SEQUENCE,BOOST_VMD_TYPE_TUPLE) will return emptiness BOOST_VMD_ELEM(4,A_SEQUENCE) will return ANAME BOOST_VMD_ELEM(4,A_SEQUENCE,BOOST_VMD_TYPE_IDENTIFIER) will return ANAME BOOST_VMD_ELEM(4,A_SEQUENCE,BOOST_VMD_TYPE_NUMBER) will return emptiness BOOST_VMD_ELEM(0,BOOST_PP_NIL) will return BOOST_PP_NIL BOOST_VMD_ELEM(0,BOOST_PP_NIL,BOOST_VMD_TYPE_LIST) will return BOOST_PP_NIL since it is an empty list BOOST_VMD_ELEM(0,BOOST_PP_NIL,BOOST_VMD_TYPE_IDENTIFIER) will return BOOST_PP_NIL since it a registered identifier BOOST_VMD_ELEM(0,BOOST_PP_NIL,BOOST_VMD_TYPE_TUPLE) will return emptiness
If you specify more than one v-type as a filtering modifier to BOOST_VMD_ELEM the last v-type becomes the filter.
Filtering with BOOST_VMD_ELEM denotes the type of the data expected when the particular element is found. Because filtering represents the type of the data requested, filtering modifiers and return type modifiers are mutually exclusive and any filtering modifier means that return type modifiers specified are ignored.