Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Asserting and data types

The VMD macros for identifying v-types work best when the macro logic can take different paths depending on the type of data being passed for a macro parameter. But occasionally the preprocessor metaprogrammer wants to simply verify that the macro parameter data is of the correct v-type, else a preprocessor error should be generated to notify the programmer invoking the macro that the data passed is the incorrect type.

Using BOOST_VMD_ASSERT

The Boost PP library has a macro which produces a preprocessor error when the condition passed to it is 0. This macro is called BOOST_PP_ASSERT. The macro produces a preprocessor error by forcing a call to an internal macro with the wrong number of arguments. According to the C++ standard this should always cause an immediate preprocessor error for conforming compilers.

Unfortunately VC++ will only produce a warning when the wrong number of arguments are passed to a macro. Therefore the BOOST_PP_ASSERT macro does not produce a preprocessing error using VC++. Amazingly enough there appears to be no other way in which VC++ can be forced to issue a preprocessng error by invoking a macro ( if you find one please tell me about it ). However one can create invalid C++ as the output from a macro invocation which causes VC++ to produce a compiler error when the VC++ compiler later encounters the construct.

This is what the macro BOOST_VMD_ASSERT does. It takes the same conditional argument as BOOST_PP_ASSERT and it calls BOOST_PP_ASSERT when not used with VC++, otherwise if the condition is 0 it generates a compiler error by generating invalid C++ when used with VC++. The compiler error is generated by producing invalid C++ whose form is:

typedef char BOOST_VMD_ASSERT_ERROR[-1];

By passing a second optional argument, whose form is a preprocessing identifier, to BOOST_VMD_ASSERT you can generate the invalid C++ for VC++, if the first argument is 0, of the form:

typedef char optional_argument[-1];

instead. This may give a little more clarity, if desired, to the C++ error generated.

If the first conditional argument is not 0, BOOST_VMD_ASSERT produces no output.

BOOST_VMD_ASSERT Usage

To use the BOOST_VMD_ASSERT macro either include the general header:

#include <boost/vmd/vmd.hpp>

or include the specific header:

#include <boost/vmd/assert.hpp>

Assertions for VMD data types

The v-types have their own assertion macros. These are largely just shortcuts for passing the result of the identifying macros to BOOST_VMD_ASSERT. These assertion macros are:

Each of these macros take as parameters the exact same argument as their corresponding identifying macros. But instead of returning non-zero or 0, each of these macros produce a compiler error if the type of the input is not correct.

Each of these macros only check for its assertion when the macro BOOST_VMD_ASSERT_DATA is set to 1. By default BOOST_VMD_ASSERT_DATA is only set to 1 in compiler debug mode. The programmer can manually set BOOST_VMD_ASSERT_DATA to 1 prior to using one the data types assert macros if he wishes.

BOOST_VMD_ASSERT_... Usage

To use the individual BOOST_VMD_ASSERT_... macros either include the general header:

#include <boost/vmd/vmd.hpp>

or include the specific header:

#include <boost/vmd/is_empty.hpp> // BOOST_VMD_ASSERT_IS_EMPTY
#include <boost/vmd/is_identifier.hpp> // BOOST_VMD_ASSERT_IS_IDENTIFIER
#include <boost/vmd/is_number.hpp> // BOOST_VMD_ASSERT_IS_NUMBER
#include <boost/vmd/array.hpp> // BOOST_VMD_ASSERT_IS_ARRAY
#include <boost/vmd/list.hpp> // BOOST_VMD_ASSERT_IS_LIST
#include <boost/vmd/seq.hpp> // BOOST_VMD_ASSERT_IS_SEQ
#include <boost/vmd/tuple.hpp> // BOOST_VMD_ASSERT_IS_TUPLE

Assertions and VC++

The VC++ compiler has a quirk when dealing with BOOST_VMD_ASSERT and the v-type assert macros. If you invoke one of the assert macros within another macro which would normally generate output preprocessor tokens, it is necessary when using VC++ to concatenate the result of the assert macro to whatever other preprocessor data is being generated, even if the assert macro does not generate an error.

As a simple example let us suppose we have a macro expecting a tuple and generating 1 if the tuple has more than 2 elements, otherwise it generates 0. Ordinarily we could write:

#define AMACRO(atuple) \
    BOOST_VMD_ASSERT_IS_TUPLE(atuple) \
    BOOST_PP_IIF(BOOST_PP_GREATER(BOOST_PP_TUPLE_SIZE(atuple), 2),1,0)

but for VC++ we must write

#define AMACRO(atuple) \
    BOOST_PP_CAT \
       ( \
       BOOST_VMD_ASSERT_IS_TUPLE(atuple), \
       BOOST_PP_IIF(BOOST_PP_GREATER(BOOST_PP_TUPLE_SIZE(atuple), 2),1,0) \
       )

VC++ does not work correctly in the first instance, erroneously getting confused as far as compiler ouput is concerned. But by using BOOST_PP_CAT in the second condition VC++ will work correctly with VMD assertions.


PrevUpHomeNext