123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- // (C) Copyright Edward Diener 2011-2015
- // Use, modification and distribution are subject to 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).
- #if !defined(BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP)
- #define BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP
- //[ example_switch
- #include <boost/vmd/detail/setup.hpp>
- #if BOOST_PP_VARIADICS
- #include <boost/preprocessor/cat.hpp>
- #include <boost/preprocessor/arithmetic/inc.hpp>
- #include <boost/preprocessor/comparison/equal.hpp>
- #include <boost/preprocessor/control/expr_iif.hpp>
- #include <boost/preprocessor/control/iif.hpp>
- #include <boost/preprocessor/control/while.hpp>
- #include <boost/preprocessor/tuple/elem.hpp>
- #include <boost/preprocessor/tuple/enum.hpp>
- #include <boost/preprocessor/facilities/expand.hpp>
- #include <boost/preprocessor/tuple/replace.hpp>
- #include <boost/preprocessor/tuple/size.hpp>
- #include <boost/preprocessor/variadic/to_tuple.hpp>
- #include <boost/preprocessor/variadic/size.hpp>
- #include <boost/vmd/equal.hpp>
- #include <boost/vmd/identity.hpp>
- #include <boost/vmd/is_empty.hpp>
- /*
- State index into state values
- */
- #define BOOST_VMD_SWITCH_STATE_ELEM_INDEX 2
- #define BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT 4
- #define BOOST_VMD_SWITCH_STATE_ELEM_RESULT 5
- /*
- Retrieve the state value, never changes
- */
- #define BOOST_VMD_SWITCH_STATE_GET_VALUE(state) \
- BOOST_PP_TUPLE_ELEM(0,state) \
- /**/
- /*
- Retrieve the state tuple of values, never changes
- */
- #define BOOST_VMD_SWITCH_STATE_GET_CHOICES(state) \
- BOOST_PP_TUPLE_ELEM(1,state) \
- /**/
- /*
- Retrieve the state index
- */
- #define BOOST_VMD_SWITCH_STATE_GET_INDEX(state) \
- BOOST_PP_TUPLE_ELEM(2,state) \
- /**/
- /*
- Retrieve the state tuple of values size, never changes
- */
- #define BOOST_VMD_SWITCH_STATE_GET_SIZE(state) \
- BOOST_PP_TUPLE_ELEM(3,state) \
- /**/
- /*
- Retrieve the state default tuple
- */
- #define BOOST_VMD_SWITCH_STATE_GET_DEFAULT(state) \
- BOOST_PP_TUPLE_ELEM(4,state) \
- /**/
- /*
- Retrieve the state result tuple
- */
- #define BOOST_VMD_SWITCH_STATE_GET_RESULT(state) \
- BOOST_PP_TUPLE_ELEM(5,state) \
- /**/
- /*
- Retrieve the current value tuple
- */
- #define BOOST_VMD_SWITCH_STATE_GET_CURRENT_CHOICE(state) \
- BOOST_PP_TUPLE_ELEM \
- ( \
- BOOST_VMD_SWITCH_STATE_GET_INDEX(state), \
- BOOST_VMD_SWITCH_STATE_GET_CHOICES(state) \
- ) \
- /**/
- /*
- Expands to the state
-
- value = value to compare against
- tuple = choices as a tuple of values
- size = size of tuple of values
-
- None of these ever change in the WHILE state
- */
- #define BOOST_VMD_SWITCH_STATE_EXPAND(value,tuple,size) \
- (value,tuple,0,size,(0,),(,)) \
- /**/
- /*
- Expands to the WHILE state
- The state to our WHILE consists of a tuple of elements:
-
- 1: value to compare against
- 2: tuple of values. Each value is a value/macro pair or if the default just a macro
- 3: index into the values
- 4: tuple for default macro. 0 means no default macro, 1 means default macro and then second value is the default macro.
- 5: tuple of result matched. Emptiness means no result yet specified, 0 means no match, 1 means match and second value is the matching macro.
- */
- #define BOOST_VMD_SWITCH_STATE(value,...) \
- BOOST_VMD_SWITCH_STATE_EXPAND \
- ( \
- value, \
- BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__), \
- BOOST_PP_VARIADIC_SIZE(__VA_ARGS__) \
- ) \
- /**/
- /*
- Sets the state upon a successful match.
-
- macro = is the matching macro found
- */
- #define BOOST_VMD_SWITCH_OP_SUCCESS(d,state,macro) \
- BOOST_PP_TUPLE_REPLACE_D \
- ( \
- d, \
- state, \
- BOOST_VMD_SWITCH_STATE_ELEM_RESULT, \
- (1,macro) \
- ) \
- /**/
- /*
- Sets the state upon final failure to find a match.
-
- def = default tuple macro, ignored
- */
- #define BOOST_VMD_SWITCH_OP_FAILURE(d,state,def) \
- BOOST_PP_TUPLE_REPLACE_D \
- ( \
- d, \
- state, \
- BOOST_VMD_SWITCH_STATE_ELEM_RESULT, \
- (0,) \
- ) \
- /**/
- /*
- Increments the state index into the tuple values
- */
- #define BOOST_VMD_SWITCH_OP_UPDATE_INDEX(d,state) \
- BOOST_PP_TUPLE_REPLACE_D \
- ( \
- d, \
- state, \
- BOOST_VMD_SWITCH_STATE_ELEM_INDEX, \
- BOOST_PP_INC(BOOST_VMD_SWITCH_STATE_GET_INDEX(state)) \
- ) \
- /**/
- /*
- Choose our current value's macro as our successful match
- tuple = current tuple to test
-
- */
- #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_MATCH(d,state,tuple) \
- BOOST_VMD_SWITCH_OP_SUCCESS(d,state,BOOST_PP_TUPLE_ELEM(1,tuple)) \
- /**/
- /*
- Update our state index
- tuple = current tuple to test, ignored
-
- */
- #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_UPDATE_INDEX(d,state,tuple) \
- BOOST_VMD_SWITCH_OP_UPDATE_INDEX(d,state) \
- /**/
- /*
- Test our current value against our value to compare against
- tuple = current tuple to test
-
- */
- #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE(d,state,tuple) \
- BOOST_PP_IIF \
- ( \
- BOOST_VMD_EQUAL_D \
- ( \
- d, \
- BOOST_VMD_SWITCH_STATE_GET_VALUE(state), \
- BOOST_PP_TUPLE_ELEM(0,tuple) \
- ), \
- BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_MATCH, \
- BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_UPDATE_INDEX \
- ) \
- (d,state,tuple) \
- /**/
- /*
- Set our default macro and update the index in our WHILE state
- tuple = current tuple to test
-
- */
- #if BOOST_VMD_MSVC
- #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT_NN(number,name) \
- (number,name) \
- /**/
- #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT(d,state,tuple) \
- BOOST_VMD_SWITCH_OP_UPDATE_INDEX \
- ( \
- d, \
- BOOST_PP_TUPLE_REPLACE_D \
- ( \
- d, \
- state, \
- BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT, \
- BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT_NN(1,BOOST_PP_TUPLE_ENUM(tuple)) \
- ) \
- ) \
- /**/
- #else
- #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT(d,state,tuple) \
- BOOST_VMD_SWITCH_OP_UPDATE_INDEX \
- ( \
- d, \
- BOOST_PP_TUPLE_REPLACE_D \
- ( \
- d, \
- state, \
- BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT, \
- (1,BOOST_PP_TUPLE_ENUM(tuple)) \
- ) \
- ) \
- /**/
- #endif
- /*
- If our current value is a default macro, just set the default macro,
- else test our current value.
-
- tuple = current tuple to test
- */
- #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_TUPLE(d,state,tuple) \
- BOOST_PP_IIF \
- ( \
- BOOST_PP_EQUAL_D \
- ( \
- d, \
- BOOST_PP_TUPLE_SIZE(tuple), \
- 1 \
- ), \
- BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT, \
- BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE \
- ) \
- (d,state,tuple) \
- /**/
- /*
- Test the current value in our tuple of values
- */
- #define BOOST_VMD_SWITCH_OP_TEST_CURRENT(d,state) \
- BOOST_VMD_SWITCH_OP_TEST_CURRENT_TUPLE \
- ( \
- d, \
- state, \
- BOOST_VMD_SWITCH_STATE_GET_CURRENT_CHOICE(state) \
- ) \
- /**/
- /*
- Choose the default macro as our successful match
-
- def = default tuple consisting of just the default macro name
- */
- #define BOOST_VMD_SWITCH_OP_DEFAULT_RET_CHOSEN(d,state,def) \
- BOOST_VMD_SWITCH_OP_SUCCESS \
- ( \
- d, \
- state, \
- BOOST_PP_TUPLE_ELEM(1,def) \
- ) \
- /**/
- /*
- If the default macro exists, choose it else indicate no macro was found
- def = default tuple consisting of just the default macro name
-
- */
- #define BOOST_VMD_SWITCH_OP_DEFAULT_RET(d,state,def) \
- BOOST_PP_IIF \
- ( \
- BOOST_PP_TUPLE_ELEM(0,def), \
- BOOST_VMD_SWITCH_OP_DEFAULT_RET_CHOSEN, \
- BOOST_VMD_SWITCH_OP_FAILURE \
- ) \
- (d,state,def) \
- /**/
- /*
- Try to choose the default macro if it exists
- */
- #define BOOST_VMD_SWITCH_OP_DEFAULT(d,state) \
- BOOST_VMD_SWITCH_OP_DEFAULT_RET \
- ( \
- d, \
- state, \
- BOOST_VMD_SWITCH_STATE_GET_DEFAULT(state) \
- ) \
- /**/
- /*
- WHILE loop operation
-
- Check for the next value match or try to choose the default if all matches have been checked
- */
- #define BOOST_VMD_SWITCH_OP(d,state) \
- BOOST_PP_IIF \
- ( \
- BOOST_PP_EQUAL_D \
- ( \
- d, \
- BOOST_VMD_SWITCH_STATE_GET_INDEX(state), \
- BOOST_VMD_SWITCH_STATE_GET_SIZE(state) \
- ), \
- BOOST_VMD_SWITCH_OP_DEFAULT, \
- BOOST_VMD_SWITCH_OP_TEST_CURRENT \
- ) \
- (d,state) \
- /**/
- /*
- WHILE loop predicate
-
- Continue the WHILE loop if a result has not yet been specified
- */
- #define BOOST_VMD_SWITCH_PRED(d,state) \
- BOOST_VMD_IS_EMPTY \
- ( \
- BOOST_PP_TUPLE_ELEM \
- ( \
- 0, \
- BOOST_VMD_SWITCH_STATE_GET_RESULT(state) \
- ) \
- ) \
- /**/
- /*
- Invokes the function-like macro
-
- macro = function-like macro name
- tparams = tuple of macro parameters
- */
- #define BOOST_VMD_SWITCH_PROCESS_INVOKE_MACRO(macro,tparams) \
- BOOST_PP_EXPAND(macro tparams) \
- /**/
- /*
- Processes our WHILE loop result
-
- callp = tuple of parameters for the called macro
- result = tuple. The first tuple element is 0
- if no macro has been found or 1 if a macro
- has been found. If 1 the second element is
- the name of a function-like macro
- */
- #define BOOST_VMD_SWITCH_PROCESS(callp,result) \
- BOOST_PP_EXPR_IIF \
- ( \
- BOOST_PP_TUPLE_ELEM(0,result), \
- BOOST_VMD_SWITCH_PROCESS_INVOKE_MACRO \
- ( \
- BOOST_PP_TUPLE_ELEM(1,result), \
- callp \
- ) \
- ) \
- /**/
- /*
- Use BOOST_VMD_SWITCH_IDENTITY to pass a fixed value instead
- of a function-like macro as the second element of
- any tuple of the variadic parameters, or as the default
- value, to BOOST_VMD_SWITCH.
-
- */
- #if BOOST_VMD_MSVC
- #define BOOST_VMD_SWITCH_IDENTITY(item) BOOST_PP_CAT(BOOST_VMD_IDENTITY(item),)
- #else
- #define BOOST_VMD_SWITCH_IDENTITY BOOST_VMD_IDENTITY
- #endif
- /*
- Switch macro
-
- Parameters are:
-
- value = value to compare against. May be any VMD data value.
- callp = tuple of parameters for the called macro
- variadic parameters = each parameter must be a tuple.
- Each tuple consists of a two-element tuple. The first element is
- a value, which may be any VMD data value, and the second element
- is the name of a function-like macro to be called if the value
- is equal to the value to compare against. For a default value
- the tuple is a single-element tuple which contains the name of
- a function-like macro to be called if no other value matches.
- */
- #define BOOST_VMD_SWITCH(value,callp,...) \
- BOOST_VMD_SWITCH_PROCESS \
- ( \
- callp, \
- BOOST_VMD_SWITCH_STATE_GET_RESULT \
- ( \
- BOOST_PP_WHILE \
- ( \
- BOOST_VMD_SWITCH_PRED, \
- BOOST_VMD_SWITCH_OP, \
- BOOST_VMD_SWITCH_STATE(value,__VA_ARGS__) \
- ) \
- ) \
- ) \
- /**/
- #endif /* BOOST_PP_VARIADICS */
- //]
-
- #endif /* BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP */
|