Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Overriding the default choosing algorithm

The default algorithm employed by CXXD to choose whether to use a Boost library or its C++ standard equivalent for any mod is very simple. If the C++ standard library is available during compilation it is chosen and if it is not available during compilation its equivalent Boost library is chosen.

The determination of availability for any given mod is done by examining Boost Config macros. Boost Config has quite a number of macros which will specify which C++ standard library is available during compilation. The logic of determining which library is available is determined within Boost Config, and CXXD just uses the results of that logic to configure the macros for a particular mod.

The logic of setting the macros for any particular mod occurs when the mod implementation header for that mod is included in the code. Each mod header automatically includes its corresponding mod implementation header, so the programmer need only include the mod header to cause the choice to be made. The logic is completely preprocessor macro based, and is specific to each mod implemenattion header, although the logic for each mod implementation header is generally the same.

As an example, using the regex mod:

#include <boost/cxx_dual/regex.hpp>
... code

If Boost Config determines that the C++ standard regex library is available CXXD_HAS_STD_REGEX is defined as '1', CXXD_REGEX_NS is defined as 'std', and CXXD_REGEX_HEADER is defined as '<regex>'. If Boost Config determines that the C++ standard regex library is not available CXXD_HAS_STD_REGEX is defined as '0', CXXD_REGEX_NS is defined as 'boost', and CXXD_REGEX_HEADER is defined as '<boost/regex.hpp>'.

Overriding the choice

Although CXXD chooses automatically whether the Boost library or the C++ standard library is to be used for any given mod the programmer may decide to override this choice. The method of overriding the choice is to define a particular macro before including a particular mod header.

The programmer may override the automatic choice of CXXD by specifying that the Boost library be used or by specifying that the C++ standard library be used. If the programmer specifies that the C++ standard library be used and that library is not available for use, a preprocessor error will normally be generated.

While it may seem reasonable that the programmer can override the choice by specifying that the Boost library be chosen for a particular mod, it might seem odd that programmer should be able to override the choice by specifying that the C++ standard library be chosen for a particular mod, considering the fact that the default choosing algorithm will automatically choose the C++ standard library if it is available. Specific cases for allowing this will be discussed later in the documentation, but the general case is that it is possible that a programmer, when using a particular mod, wants to makes sure that the C++ standard library is available. else he wants to force a preprocessing error.

Specific overriding

For any given mod 'XXX' defining a macro called CXXD_'XXX'_USE_BOOST specifies that the Boost library will be used. If used CXXD_'XXX'_USE_BOOST must always be defined to expand to nothing, as in:

#define CXXD_'XXX'_USE_BOOST

where XXX is the uppercase name of the mod.

For any given mod 'XXX' defining a macro called CXXD_'XXX'_USE_STD specifies that the C++ standard library will be used. If used CXXD_'XXX'_USE_STD must always be defined to nothing, as in:

#define CXXD_'XXX'_USE_STD

where XXX is the uppercase name of the mod.

The specific override macros for each mod are:

Table 1.6. Specific override macros

Mod

Boost override macro

C++ standard override macro

array

CXXD_ARRAY_USE_BOOST

CXXD_ARRAY_USE_STD

atomic

CXXD_ATOMIC_USE_BOOST

CXXD_ATOMIC_USE_STD

bind

CXXD_BIND_USE_BOOST

CXXD_BIND_USE_STD

chrono

CXXD_CHRONO_USE_BOOST

CXXD_CHRONO_USE_STD

condition_variable

CXXD_CONDITION_VARIABLE_USE_BOOST

CXXD_CONDITION_VARIABLE_USE_STD

enable_shared_from_this

CXXD_ENABLE_SHARED_FROM_THIS_USE_BOOST

CXXD_ENABLE_SHARED_FROM_THIS_USE_STD

function

CXXD_FUNCTION_USE_BOOST

CXXD_FUNCTION_USE_STD

hash

CXXD_HASH_USE_BOOST

CXXD_HASH_USE_STD

make_shared

CXXD_MAKE_SHARED_USE_BOOST

CXXD_MAKE_SHARED_USE_STD

mem_fn

CXXD_MEM_FN_USE_BOOST

CXXD_MEM_FN_USE_STD

move

CXXD_MOVE_USE_BOOST

CXXD_MOVE_USE_STD

mutex

CXXD_MUTEX_USE_BOOST

CXXD_MUTEX_USE_STD

random

CXXD_RANDOM_USE_BOOST

CXXD_RANDOM_USE_STD

ratio

CXXD_RATIO_USE_BOOST

CXXD_RATIO_USE_STD

ref

CXXD_REF_USE_BOOST

CXXD_REF_USE_STD

regex

CXXD_REGEX_USE_BOOST

CXXD_REGEX_USE_STD

shared_mutex

CXXD_SHARED_MUTEX_USE_BOOST

CXXD_SHARED_MUTEX_USE_STD

shared_ptr

CXXD_SHARED_PTR_USE_BOOST

CXXD_SHARED_PTR_USE_STD

system_error

CXXD_SYSTEM_ERROR_USE_BOOST

CXXD_SYSTEM_ERROR_USE_STD

thread

CXXD_THREAD_USE_BOOST

CXXD_THREAD_USE_STD

tuple

CXXD_TUPLE_USE_BOOST

CXXD_TUPLE_USE_STD

type_index

CXXD_TYPE_INDEX_USE_BOOST

CXXD_TYPE_INDEX_USE_STD

type_traits

CXXD_TYPE_TRAITS_USE_BOOST

CXXD_TYPE_TRAITS_USE_STD

unordered_map

CXXD_UNORDERED_MAP_USE_BOOST

CXXD_UNORDERED_MAP_USE_STD

unordered_multimap

CXXD_UNORDERED_MULTIMAP_USE_BOOST

CXXD_UNORDERED_MULTIMAP_USE_STD

unordered_multiset

CXXD_UNORDERED_MULTISET_USE_BOOST

CXXD_UNORDERED_MULTISET_USE_STD

unordered_set

CXXD_UNORDERED_SET_USE_BOOST

CXXD_UNORDERED_SET_USE_STD

weak_ptr

CXXD_WEAK_PTR_USE_BOOST

CXXD_WEAK_PTR_USE_STD


If for any given mod 'XXX' both CXXD_'XXX'_USE_BOOST and CXXD_'XXX'_USE_STD is defined a preprocessing error will occur when the mod header for 'XXX' is included.

As examples, using the regex mod:

#define CXXD_REGEX_USE_BOOST
#include <boost/cxx_dual/regex.hpp>
... code

CXXD_HAS_STD_REGEX is defined as '0', CXXD_REGEX_NS is defined as 'boost', and CXXD_REGEX_HEADER is defined as '<boost/regex.hpp>'.

#define CXXD_REGEX_USE_STD
#include <boost/cxx_dual/regex.hpp>
... code

CXXD_HAS_STD_REGEX is defined as '1', CXXD_REGEX_NS is defined as 'std', and CXXD_REGEX_HEADER is defined as '<regex>', as long as the C++ standard regex library is available for use, else a preprocessing error is generated.

General overriding

Along with the specific macros of the form CXXD_'XXX'_USE_BOOST and CXXD_'XXX'_USE_STD which override default processing for the specific 'xxx' mod the programmer can specify either of two generalized macros which overrides default processing for any mod.

Defining a macro called CXXD_USE_BOOST specifies that the Boost library will be used for any mod. If used CXXD_USE_BOOST must always be defined to nothing, as in:

#define CXXD_USE_BOOST

Defining a macro called CXXD_USE_STD specifies that the C++ standard library will be used for any mod. If used CXXD_USE_STD must always be defined to nothing, as in:

#define CXXD_USE_STD

If both CXXD_USE_BOOST and CXXD_USE_STD is defined a preprocessing error will occur when any mod header is included.

If for any given mod 'xxx' both CXXD_'XXX'_USE_BOOST and CXXD_USE_STD is defined a preprocessing error will occur when the mod header file for 'xxx' is included.

If for any given mod 'xxx' both CXXD_'XXX'_USE_STD and CXXD_USE_BOOST is defined a preprocessing error will occur when the mod header file for 'xxx' is included.

As examples, using the regex mod:

#define CXXD_USE_BOOST
#include <boost/cxx_dual/regex.hpp>
... code

CXXD_HAS_STD_REGEX is defined as '0', CXXD_REGEX_NS is defined as 'boost', and CXXD_REGEX_HEADER is defined as '<boost/regex.hpp>'.

#define CXXD_USE_STD
#include <boost/cxx_dual/regex.hpp>
... code

CXXD_HAS_STD_REGEX is defined as '1', CXXD_REGEX_NS is defined as 'std', and CXXD_REGEX_HEADER is defined as '<regex>'. as long as the C++ standard regex library is available for use, else a preprocessing error is generated.

#define CXXD_REGEX_USE_BOOST
#define CXXD_USE_STD
#include <boost/cxx_dual/regex.hpp>
... code

A preprocessing error is generated.

#define CXXD_REGEX_USE_STD
#define CXXD_USE_BOOST
#include <boost/cxx_dual/regex.hpp>
... code

A preprocessing error is generated.

Using any CXXD mod header:

#define CXXD_USE_BOOST
#define CXXD_USE_STD
#include <boost/cxx_dual/'any_cxxd_mod_header'
... code

A preprocessing error is generated.

Purpose of overriding

The purpose of using overriding macros, for any mod with the specific overriding macros or for CXXD as a whole with the general overriding macros, is to override the default algorithm which CXXD uses to choose a dual library. However using overriding macros for one's own direct use(s) of CXXD is generally foolish. This is because the easiest implementation, rather than using an overriding macro, is to just to not use CXXD for a mod in favor of using either the Boost library or C++ standard library directly.

In other words, instead of:

#define CXXD_USE_BOOST
#include <boost/cxx_dual/regex.hpp>
cxxd_regex_ns::regex my_regex; // etc.
... code

you can simply code:

#include <boost/regex.hpp>
boost::regex my_regex; // etc.
... code

and instead of:

#define CXXD_USE_STD
#include <boost/cxx_dual/regex.hpp>
cxxd_regex_ns::regex my_regex; // etc.
... code

you can simply code:

#include <regex>
std::regex my_regex; // etc.
... code

In this sense the examples given above of using specific or general overriding macros are purely artificial in order to merely show what the meaning of these overriding macros entail. In actual code directly overriding a particular mod should almost never be done in favor of directly using either the Boost or C++ standard implementations of a dual library.

So what is the actual purpose of the overriding macros ? The purpose is to override the use of CXXD by another library whose source files can not or should not be modified. A third-party library may choose to use CXXD to provide a dual library for a particular mod. Your own code, which uses the third-party library but otherwise uses either the Boost version of the dual library or the C++ standard version of the dual library in all other situations, may enforce its own usage on the dual library interface of the third-party library by using an overriding macro. As an example a third-party library might have as a public interface:

// Header file ThirdPartyHeader.hpp
#include <boost/cxx_dual/regex.hpp>
class ThirdPartyClass
    {
    public:
    void SomeFunction(cxxd_regex_ns::regex &);
    ... // other functionality
    };

We will assume, in this instance, this is a header-only library ( an extended discussion of using CXXD with a non-header-only library will follow later in the documentation ). In one's own code you may desire to use the ThirdPartyClass::SomeFunction interface with specifically the Boost regex library only. Your own code might then look like:

#define CXXD_REGEX_USE_BOOST
#include <ThirdPartyHeader.hpp>
boost::regex my_regex("SomeRegularExpression etc.");
ThirdPartyClass tpclass;
tpclass.SomeFunction(my_regex);

Conversely you may decide that your use of the ThirdPartyClass::SomeFunction interface should be with the C++ standard regex library only, so your code might then look like:

#define CXXD_REGEX_USE_STD
#include <ThirdPartyHeader.hpp>
std::regex my_regex("SomeRegularExpression etc.");
ThirdPartyClass tpclass;
tpclass.SomeFunction(my_regex);

Instead if you did accept the dual nature of the ThirdPartyHeader.hpp header, your code might then like:

#include <ThirdPartyHeader.hpp>
cxxd_regex_ns::regex my_regex("SomeRegularExpression etc.");
ThirdPartyClass tpclass;
tpclass.SomeFunction(my_regex);

In other words using the overriding macros of CXXD serves the purpose of using some already established interface involving CXXD without changing that interface's own code, at the same time forcing the choice of a particular dual library to be used. We can say that overriding macros change the dual library nature of a mod to a single library interface.

Overriding one's own interface

There is a situation where the programmer may choose to override his own use of a particular mod. This is when he programs his own interface using a particular mod but decides for a particular combination of compiler and/or OS that he wants to override that choice. In other words the programmer wishes to use a dual library for the benefits that CXXD has to offer but knows that for some combination of compiler and/or operating system that the particular dual library choice must be overridden for a reason, perhaps to prevent a faulty library implementation from being used.

Let's imagine that for a particular compiler version 'CCC' version 'NNN' on a particular OS 'OOO' we know that the standard library version of mod 'XXX' is buggy. Also let's imagine that we can test for the buggy combination through using the preprocessor defines, as we can do in Boost through either Boost.Config or even more easily through Boost.Predef. Our pseudocode for overriding our own use of the dual library in a header file might look like:

// Header file OwnOverrideHeader.hpp
#if CCCNNN && OOO
#define CXXD_XXX_USE_BOOST
#endif
#include <boost/cxx_dual/XXX.hpp>
class OwnOverrideClass
    {
    public:
    void SomeOwnOverrideFunction(cxxd_xxx_ns::xxx_object &);
    ... // other functionality
    };

So essentially where the purpose of the override macros is to change another interface's dual library choice for a particular mod to a single library, you can use the override macros with one's own interface in order to provide one-off situations where you want to specifically control the library chosen for a mod for a particular compiling environment.


PrevUpHomeNext