////
Copyright (c) 2024 The C++ Alliance, Inc. (https://cppalliance.org)

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)

Official repository: https://github.com/boostorg/website-v2-docs
////
= Boost Macros
:navtitle: Macros

Boost provides many useful macros that help with configuration, debugging, portability, and convenience when working with the libraries. 

There are thousands of defined macros (refer to the https://www.boost.org/doc/libs/latest/libs/config/doc/html/boost_config/boost_macro_reference.html[Boost Macro Reference]). However, here are some of the most commonly used, and some sample code showing how to work them into your code.

[square]
* <<Library Inclusion and Linking>>
* <<Configuration and Compiler Detection>>
* <<Debugging and Assertions>>
* <<Preprocessor Utilities>>
* <<Cross-Platform Compatibility>>
* <<Threading and Synchronization>>
* <<Exception Handling>>
* <<See Also>>

Notes:: Most of the macros do not take any parameters. Those that do have `(..)` in the tables below.
+
The code in this topic was written and tested using Microsoft Visual Studio (Visual C++ 2022, Console App project) with Boost version 1.88.0.

== Library Inclusion and Linking

[cols="1,2,2,2",options="header",stripes=even,frame=none]
|===
| *Macro* | *Description* | *Defined In* | *Include Required?*
| `BOOST_ALL_NO_LIB` | Disables automatic linking for all Boost libraries. | `<boost/config/auto_link.hpp>` | Usually No (via other Boost headers) 
| `BOOST_LIB_DIAGNOSTIC` | Enables diagnostic output for automatic linking. | `<boost/config/auto_link.hpp>` | Usually No 
| `BOOST_ALL_DYN_LINK` | Forces all Boost libraries to be linked dynamically. | `<boost/config/auto_link.hpp>` | Usually No 
|===

=== Example

The `BOOST_ALL_NO_LIB` macro prevents automatic linking of Boost libraries.

[source,cpp]
----
#define BOOST_ALL_NO_LIB  // Disable auto-linking

#include <boost/filesystem.hpp>
#include <iostream>

int main() {
    std::cout << "Boost Filesystem is included, but auto-linking is disabled.\n";
}

----

== Configuration and Compiler Detection

[cols="1,2,2,2",options="header",stripes=even,frame=none]
|===
| *Macro* | *Description* | *Defined In* | *Include Required?*
| `BOOST_VERSION` | Defines the Boost version as an integer (for example, 107800 for Boost 1.78.0). | `<boost/version.hpp>` | Yes 
| `BOOST_PLATFORM` | Identifies the platform (for example, Windows, Linux). | `<boost/config.hpp>` | Yes 
| `BOOST_COMPILER` | Identifies the compiler in use (for example, gcc, msvc). | `<boost/config.hpp>` | Yes 
| `BOOST_STDLIB` | Identifies the standard library (for example, libstdc++, msvc). | `<boost/config.hpp>` | Yes 
| `BOOST_SP_USE_QUICK_ALLOCATOR` | Optimizes memory allocation for `shared_ptr`. | `<boost/smart_ptr/detail/sp_counted_base.hpp>` | Yes (if used directly) 
| `BOOST_NO_CXX11_SMART_PTR` | Defined if C++11 smart pointers are not available. | `<boost/config.hpp>` | Yes 
| `BOOST_STATIC_CONSTANT` | Defines compile-time constants compatible with older C++ versions. | `<boost/config.hpp>` | Yes 
| `BOOST_FILESYSTEM_VERSION` | Defines the version of boost:filesystem[] being used. | `<boost/filesystem/config.hpp>` | Usually No (via `<boost/filesystem.hpp>`) 
| `BOOST_NO_CXX11_LAMBDAS` | Defined if C++11 lambdas are not available. | `<boost/config.hpp>` | Yes 
| `BOOST_FILESYSTEM_NO_DEPRECATED` | Disables deprecated boost:filesystem[] features. | `<boost/filesystem/config.hpp>` | Usually No
|===

=== Examples

The `BOOST_STDLIB` macro is part of boost:config[] and identifies the standard library implementation being used (for example, GNU pass:[libstdc++], Microsoft STL, or pass:[libc++]). This is useful when writing code that needs to adapt to different standard library behaviors. `BOOST_STDLIB` expands to a string representing the detected standard library.

[source,cpp]
----
#include <boost/config.hpp>
#include <iostream>

int main() {
    std::cout << "Detected Standard Library: " << BOOST_STDLIB << std::endl;

#ifdef BOOST_LIBSTD_GNU
    std::cout << "Using GNU libstdc++" << std::endl;
#elif defined(BOOST_LIBSTD_MSVC)
    std::cout << "Using Microsoft STL (MSVC Standard Library)" << std::endl;
#elif defined(BOOST_LIBSTD_LIBCXX)
    std::cout << "Using libc++ (Clang Standard Library)" << std::endl;
#else
    std::cout << "Using an unknown or unsupported standard library" << std::endl;
#endif

    return 0;
}

----

Using `BOOST_PLATFORM`, `BOOST_COMPILER`, and `BOOST_STDLIB` for diagnostics by identifing the system's platform, compiler, and standard library.

[source,cpp]
----
#include <iostream>
#include <boost/config.hpp>

int main() {
    std::cout << "Platform: " << BOOST_PLATFORM << std::endl;
    std::cout << "Compiler: " << BOOST_COMPILER << std::endl;
    std::cout << "Standard Library: " << BOOST_STDLIB << std::endl;
    return 0;
}

----

Using `BOOST_VERSION` to ensure version compatibility when using Boost.

[source,cpp]
----
#include <iostream>
#include <boost/version.hpp>

int main() {
    std::cout << "Boost version: " 
              << (BOOST_VERSION / 100000) << "."   // Major version
              << (BOOST_VERSION / 100 % 1000) << "." // Minor version
              << (BOOST_VERSION % 100) << std::endl; // Patch version
    return 0;
}

----

Using `BOOST_SP_USE_QUICK_ALLOCATOR` to optimize `shared_ptr`.

[source,cpp]
----
#define BOOST_SP_USE_QUICK_ALLOCATOR // Define before including Boost.SmartPtr

#include <boost/smart_ptr.hpp>
#include <iostream>

int main() {
    boost::shared_ptr<int> ptr1(new int(42));
    boost::shared_ptr<int> ptr2 = ptr1;

    std::cout << "Shared pointer value: " << *ptr1 << std::endl;
    return 0;
}

----

== Debugging and Assertions

[cols="1,2,2,2",options="header",stripes=even,frame=none]
|===
| *Macro* | *Description* | *Defined In* | *Include Required?*
| `BOOST_ASSERT`(expr) | Asserts an expression in debug builds. | `<boost/assert.hpp>` | Yes 
| `BOOST_STATIC_ASSERT`(expr) | Performs a compile-time assertion. | `<boost/static_assert.hpp>` | Yes 
| `BOOST_STATIC_ASSERT_MSG`(expr, msg) | Compile-time assertion with a message. | `<boost/static_assert.hpp>` | Yes 
| `BOOST_VERIFY`(expr) | Like `BOOST_ASSERT`, but always evaluates the expression. | `<boost/assert.hpp>` | Yes 
| `BOOST_ENABLE_ASSERT_HANDLER` | Enables a custom assertion handler. | `<boost/assert.hpp>` | Yes 
| `BOOST_ASIO_ENABLE_HANDLER_TRACKING` | Enables handler debugging in boost:asio[]. | `<boost/asio/detail/config.hpp>` | Usually No (via `<boost/asio.hpp>`)
|===

=== Examples

Using `BOOST_ASSERT`, `BOOST_STATIC_ASSERT`, and `BOOST_VERIFY` for debugging.

[source,cpp]
----
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <iostream>

void process(int value) {
    BOOST_ASSERT(value > 0 && "Value must be positive");  // Runtime assertion
}

int main() {
    BOOST_STATIC_ASSERT(sizeof(int) == 4);  // Compile-time assertion

    int x = 10;
    BOOST_VERIFY(x != 0);  // Always checks in release mode

    process(-1);  // Will trigger an assertion failure
}

----

Using `BOOST_ASIO_ENABLE_HANDLER_TRACKING` to help debug asynchronous operations by tracking handlers.

[source,cpp]
----
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING // Enable debugging before including Boost.Asio

#include <boost/asio.hpp>
#include <iostream>

int main() {
    boost::asio::io_context io;
    std::cout << "Boost.Asio handler tracking enabled!\n";
    return 0;
}

----

== Preprocessor Utilities

[cols="1,2,2,2",options="header",stripes=even,frame=none]
|===
| *Macro* | *Description* | *Defined In* | *Include Required?* 
| `BOOST_PP_REPEAT`(count, macro, data) | Repeats a macro expansion. A modern equivalent is `template<typename... T>`, as variadic templates eliminate almost all parameter repetition cases.| `<boost/preprocessor/repetition/repeat.hpp>` | Yes 
| `BOOST_PP_IF`(cond, then, else) | Preprocessor `if` construct. A more modern approach is to use `if constexpr`. | `<boost/preprocessor/control/if.hpp>` | Yes 
| `BOOST_PP_ENUM_PARAMS`(count, param) | Expands into comma-separated parameters. A modern equivalent is `template<typename... T>`. | `<boost/preprocessor/repetition/enum_params.hpp>` | Yes 
|===

=== Example

Using `BOOST_PP_REPEAT` to generate repeated code.

[source,cpp]
----
#include <boost/preprocessor/repetition/repeat.hpp>
#include <iostream>

#define PRINT_N(z, n, text) std::cout << text << " " << n << "\n";

int main() {
    BOOST_PP_REPEAT(5, PRINT_N, "Iteration");
}

----

The output from the above example should be:

[source,text]
----
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4
----
== Cross-Platform Compatibility

[cols="1,2,2,2",options="header",stripes=even,frame=none]
|===
| *Macro* | *Description* | *Defined In* | *Include Required?*
| `BOOST_WINDOWS` | Defined when compiling on Windows. | `<boost/config/platform/win32.hpp>` | Yes (include `<boost/config.hpp>`) 
| `BOOST_LINUX` | Defined when compiling on Linux. | `<boost/config/platform/linux.hpp>` | Yes 
| `BOOST_UNIX` | Defined when compiling on a Unix-like system. | `<boost/config/platform/*.hpp>` | Yes
| `BOOST_LITTLE_ENDIAN` | Defined when system is little-endian. | `<boost/predef/other/endian.h>` | Yes
| `BOOST_BIG_ENDIAN` | Defined when system is big-endian. | `<boost/predef/other/endian.h>` | Yes
|===

=== Examples

Using `BOOST_WINDOWS`, `BOOST_LINUX`, and `BOOST_UNIX` for platform-specific code. 

[source,cpp]
----
#include <iostream>
#include <boost/config.hpp>

int main() {
#ifdef BOOST_WINDOWS
    std::cout << "Running on Windows\n";
#elif defined(BOOST_LINUX)
    std::cout << "Running on Linux\n";
#elif defined(BOOST_UNIX)
    std::cout << "Running on a Unix-like system\n";
#else
    std::cout << "Unknown platform\n";
#endif
}

----

Using Using `BOOST_LITTLE_ENDIAN` and `BOOST_BIG_ENDIAN` for proper handling of byte order in serialization.

[source,cpp]
----
#include <iostream>
#include <boost/config.hpp>

int main() {
#if defined(BOOST_LITTLE_ENDIAN)
    std::cout << "System is little-endian.\n";
#elif defined(BOOST_BIG_ENDIAN)
    std::cout << "System is big-endian.\n";
#else
    std::cout << "Unknown endianness.\n";
#endif
    return 0;
}

----

== Threading and Synchronization

[cols="1,2,2,2",options="header",stripes=even,frame=none]
|===
| *Macro* | *Description* | *Defined In* | *Include Required?*
| `BOOST_DISABLE_THREADS` | Disables Boost threading support. | `<boost/config.hpp>` | Yes 
| `BOOST_HAS_THREADS` | Indicates Boost threading support is enabled. | `<boost/config.hpp>` | Yes 
| `BOOST_THREAD_USE_LIB` | Forces boost:thread[] to use static library. | `<boost/thread/detail/config.hpp>` | Usually No (via `<boost/thread.hpp>`) 
| `BOOST_THREAD_USE_DLL` | Forces boost:thread[] to use shared library. | `<boost/thread/detail/config.hpp>` | Usually No 
| `BOOST_THREAD_PROVIDES_FUTURE` | Enables future support in boost:thread[]. | `<boost/thread/detail/config.hpp>` | Usually No 
|===

=== Example

Using `BOOST_HAS_THREADS` to ensure threading support is enabled.

[source,cpp]
----
#include <boost/thread.hpp>
#include <iostream>

void threadFunc() {
    std::cout << "Hello from thread!\n";
}

int main() {
#ifdef BOOST_HAS_THREADS
    boost::thread myThread(threadFunc);
    myThread.join();
#else
    std::cout << "Threads are not supported.\n";
#endif
}

----

== Exception Handling

[cols="1,2,2,2",options="header",stripes=even,frame=none]
|===
| *Macro* | *Description* | *Defined In* | *Include Required?*
| `BOOST_THROW_EXCEPTION`(e) | Portable exception throwing macro. | `<boost/throw_exception.hpp>` | Yes
| `BOOST_NO_EXCEPTIONS` | Disables exception handling. | `<boost/config.hpp>` | Yes
|===

=== Examples

Using `BOOST_THROW_EXCEPTION` to throw exceptions in a portable way.

[source,cpp]
----
#include <boost/exception/exception.hpp>
#include <boost/exception/all.hpp>
#include <iostream>

struct MyException : virtual boost::exception, virtual std::exception {
    const char* what() const noexcept override {
        return "A Boost exception occurred!";
    }
};

void riskyOperation() {
    BOOST_THROW_EXCEPTION(MyException());
}

int main() {
    try {
        riskyOperation();
    } catch (const MyException& e) {
        std::cout << "Caught exception: " << e.what() << "\n";
    }
}

----

Using `BOOST_NO_EXCEPTIONS` to ensure compatibility with exception-free environments.

[source,cpp]
----
#include <iostream>
#include <boost/config.hpp>

void safe_function() {
#ifndef BOOST_NO_EXCEPTIONS
    throw std::runtime_error("Something went wrong!");
#else
    std::cerr << "Exceptions are disabled. Handling error manually.\n";
#endif
}

int main() {
    try {
        safe_function();
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
    }
}

----


== See Also

* https://www.boost.org/doc/libs/latest/libs/config/doc/html/boost_config/boost_macro_reference.html[Boost Macro Reference]
* xref:diagnostics.adoc[]
* xref:testing-debugging.adoc[]