## Using the predefs

To use the automatically defined predefs one needs to only include the single top-level header:

    #include <boost/predef.h>

This defines all the version macros known to the library. For each macro it will be defined to either a zero valued expression for when the particular item is not detected, and to a positive value if it is detected. The predef macros fall onto five categories each with macros of a particular prefix:

- `BOOST_ARCH_`for system/CPU architecture one is compiling for.
- `BOOST_COMP_` for the compiler one is using.
- `BOOST_LANG_` for language standards one is compiling against.
- `BOOST_LIB_C_` and `BOOST_LIB_STD_` for the C and C++ standard library in use.
- `BOOST_OS_` for the operating system we are compiling to.
- `BOOST_PLAT_` for platforms on top of operating system or compilers.
- `BOOST_ENDIAN_` for endianness of the os and architecture combination.
- `BOOST_HW_` for hardware specific features.
- `BOOST_HW_SIMD` for SIMD (Single Instruction Multiple Data) detection.

| Note
The detected definitions are for the configuration one is targeting during the compile. In particular in a cross-compile this means the target system, and not the host system.

One uses the individual definitions to compare against specific versions by comparing against the `BOOST_VERSION_NUMBER` macro. For example, to make a choice based on the version of the GCC C++ compiler one would:

    #include <boost/predef.h>
    #include <iostream>

    int main()
    {
      if (BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4,0,0))
        std::cout << "GCC compiler is at least version 4.0.0" << std::endl;
      else
        std::cout << "GCC compiler is at older than version 4.0.0, or not a GCC compiler" << std::endl;
      return 0;
    }

As you might notice above the `else` clause also covers the case where the particular compiler is not detected. But one can make the test also test for the detection. All predef definitions are defined as a zero (0) expression when not detected. Hence one could use the detection with a natural single condition. For example:

    #include <boost/predef.h>
    #include <iostream>

    int main()
    {
      if (BOOST_COMP_GNUC)
        std::cout << "This is GNU GCC!" << std::endl;
      else
        std::cout << "Not GNU GCC." << std::endl;
      return 0;
    }

And since the predef's are preprocessor definitions the same is possible from the preprocessor:

    #include <boost/predef.h>
    #include <iostream>

    #if BOOST_COMP_GNUC
      #if BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4,0,0)
        const char * the_compiler = "GNU GCC, of at least version 4."
      #else
        const char * the_compiler = "GNU GCC, less than version 4."
      #endif
    #else
      const char * the_compiler = "Not GNU GCC."
    #endif

    int main()
    {
      std::cout << the_compiler << std::endl;
      return 0;
    }

In addition, for each version macro defined there is an `*_AVAILABLE` macro defined only when the particular aspect is detected. I.e. a definition equivalent to:

    #if BOOST_PREDEF_ABC
      #define BOOST_PREDEF_ABC_AVAILABLE
    #endif

Also for each aspect there is a macro defined with a descriptive name of what the detection is.

#### The `*_EMULATED` macros

Predef definitions are guaranteed to be uniquely detected within one category. But there are contexts under which multiple underlying detections are possible. The well known example of this is detection of GCC and MSVC compilers which are commonly emulated by other compilers by defining the same base macros. To account for this detection headers are allowed to define `*_EMULATED` predefs when this situation is detected. The emulated predefs will be set to the version number of the detection instead of the regular predef macro for that detection. For example MSVC will set `BOOST_COMP_MSVC_EMULATED` but not set `BOOST_COM_MSVC`, and it will also set `BOOST_COMP_MSVC_AVAILABLE`.

#### Using the `BOOST_VERSION_NUMBER` macro

All the predefs are defined to be a use of the `BOOST_VERSION_NUMBER` macro. The macro takes individual major, minor, and patch value expressions:

    #define BOOST_VERSION_NUMBER( major, minor, patch ) ...

The arguments are:

1. Major version number, as a constant value expression in the range [0,99].
2. Minor version number, as a constant value expression in the range [0,99].
3. Patch-level version number, as a constant value expression in the range [0,99999].

The ranges for each are "enforced" by the use of a modulo ("%"), i.e. truncation, as opposed to a clamp. And hence this means that the limits are enforced only enough to keep from having out-of-range problems. But not enough to prevent other kinds of problems. Like exceeding the range and getting false detections, or non-detections. It is up to the individual predefs to ensure correct usage beyond the range guarantee.

The values for the arguments can be any preprocessor valid constant value expression. Only constant value arithmetic is used in the definition of the `BOOST_VERSION_NUMBER` macro and in any of the other predef macros. This means that any allowed base is possible, i.e. binary, octal, decimal, and hexadecimal. For example:

    #define MY_APPLICATION_VERSION_NUMBER BOOST_VERSION_NUMBER(2,0xA,015)

Is equivalent to:

    #define MY_APPLICATION_VERSION_NUMBER BOOST_VERSION_NUMBER(2,10,13)