Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Advanced Functionality

Low-level inclusion
Overriding the default choosing algorithm
Consistency
Using in a library
Use in a header only library
Use in a non-header only library
Support for naming library variants and testing all valid possibilities

The basic functionality of the CXXD library has been explained and should serve most programmers when using the library without having to know anything further about CXXD. The basic functionality involves including a single header file for a given mod and then using the namespace alias to program the functionality which the mod provides, with the same syntax being used no matter which library has been chosen. This functionality, along with occasional use of macros which CXXD provides for each mod, is the mainstream way of programming CXXD.

This method of programming does not necessarily change when the programmer uses the advanced functionality of CXXD, which will now be explained. Instead the advanced functionality offers further methods to help the programmer when using a dual library. The advanced functionality entails:

When you include a mod header in a TU you are actually including a separate implementation header file and then using the macros in that implementation header file to do two things:

  1. Include the C++ header file(s) for the dual library which has been chosen.
  2. Set the namespace alias to the namespace of the dual library which has been chosen.

All of the logic of choosing the dual library and of creating macros reflecting that choice is done in the low-level implementation header file. The implementation header file for each mod is in the CXXD 'boost/cxx_dual/impl' subdirectory and has the same name as its corresponding mod header in the 'boost/cxx_dual' directory.

Both the 'shared_ptr.hpp' and 'shared_ptr_all.hpp' mod headers for the shared_ptr mod use the same implementation header called 'shared_ptr.hpp'.

Header macro

All of the macros, except one, which could be used by the programmer when including a mod header have been explained as aids to using the basic functionality of CXXD. The one macro which was not explained, because it does not directly impact the basic functionality, is a macro which is used to include the C++ header file(s) needed by the dual library which has been chosen. The form of this macro is CXXD_'XXX'_HEADER for any given mod XXX:

Table 1.5. C++ header macros

Mod name

C++ header macro

array

CXXD_ARRAY_HEADER

atomic

CXXD_ATOMIC_HEADER

bind

CXXD_BIND_HEADER

chrono

CXXD_CHRONO_HEADER

condition_variable

CXXD_CONDITION_VARIABLE_HEADER

enable_shared_from_this

CXXD_ENABLE_SHARED_FROM_THIS_HEADER

function

CXXD_FUNCTION_HEADER

hash

CXXD_HASH_HEADER

make_shared

CXXD_MAKE_SHARED_HEADER

mem_fn

CXXD_MEM_FN_HEADER

move

CXXD_MOVE_HEADER

mutex

CXXD_MUTEX_HEADER

random

CXXD_RANDOM_HEADER

ratio

CXXD_RATIO_HEADER

ref

CXXD_REF_HEADER

regex

CXXD_REGEX_HEADER

shared_mutex

CXXD_SHARED_MUTEX_HEADER

shared_ptr

CXXD_SHARED_PTR_HEADER

system_error

CXXD_SYSTEM_ERROR_HEADER

thread

CXXD_THREAD_HEADER

tuple

CXXD_TUPLE_HEADER

type_index

CXXD_TYPE_INDEX_HEADER

type_traits

CXXD_TYPE_TRAITS_HEADER

unordered_map

CXXD_UNORDERED_MAP_HEADER

unordered_multimap

CXXD_UNORDERED_MULTIMAP_HEADER

unordered_multiset

CXXD_UNORDERED_MULTISET_HEADER

unordered_set

CXXD_UNORDERED_SET_HEADER

weak_ptr

CXXD_WEAK_PTR_HEADER


For all mods this C++ header macro expands to the include path of a header file using the angle bracket form ( '<' and '>' ). For a few mods this C++ header macro actually expands to a header file in the CXXD implementation detail directory, which itself includes more than one library header file. For the rest this C++ header macro expands to a single C++ header for either the Boost or C++ standard library dual library, which itself includes all constructs needed by the dual library chosen.

The shared_ptr mod implementation header also has a separate C++ header macro called 'CXXD_SHARED_PTR_ALL_HEADER'. This C++ header macro is used by the 'shared_ptr_all.hpp' mod header to include the C++ header files needed by shared_ptr, weak_ptr, make_shared, and enable_shared_from_this for either the Boost dual library or the C++ standard dual library chosen.

Low-level implementation header versus mod header

Because of the C++ header macro, and because the previously discussed namespace macro can be used anytime the namespace alias can be used, it is possible to forgo the inclusion of the mod header and use the low-level inclusion of the same-named implementation header file for any given mod. As an example, when using the regex mod the code showing basic functionality of CXXD was:

#include <boost/cxx_dual/regex.hpp>

void SomeFunction()
    {
    cxxd_regex_ns::regex re("A regular expression etc.");
    bool result(cxxd_regex_ns::regex_match("Some string...",re));
    // etc.
    }

Alternatively using the low-level implementation header the code could be:

#include <boost/cxx_dual/impl/regex.hpp>
#include CXXD_REGEX_HEADER

void SomeFunction()
    {
    CXXD_REGEX_NS::regex re("A regular expression etc.");
    bool result(CXXD_REGEX_NS::regex_match("Some string...",re));
    // etc.
    }

or even:

#include <boost/cxx_dual/impl/regex.hpp>
#include CXXD_REGEX_HEADER
namespace cxxd_regex_ns = CXXD_REGEX_NS;

void SomeFunction()
    {
    cxxd_regex_ns::regex re("A regular expression etc.");
    bool result(cxxd_regex_ns::regex_match("Some string...",re));
    // etc.
    }
Inclusion order

Once you include a mod header in a TU there is no point in separately including the low-level mod implementation header, since the mod header already does so. However separately including both the mod header and low-level mod implementation for a particular mod does no harm, no matter what order they are included or how many times they are included.

Basic low-level usage

Obviously using the low-level implementation header is more verbose as can be seen in previous examples. So why would we ever want to use it as opposed to the normal mod header ?

Including the low-level implementation header, rather than the mod header, gives the programmer specific control over which header file(s) get included for the dual library chosen and how the constructs in the dual library chosen are referred to. When including the mod header that choice is automatically made by including the most general header file(s) needed and by creating a namespace alias for referring to the top-level constructs of a dual library. Including the low-level implementation header allows the programmer to manually make such choices.

Furthermore, unlike including a mod header, including the low-level header for a mod does not create any immediate dependency on the dual library chosen. This is particularly relevant if you want to use the mod's choosing macro to write one-off code which does not use CXXD's dual library support at all.

Manual header file inclusion

Many programmers like to include specific header file rather than a general header for a library. The reasons for this are numerous but the general idea is that the programmer should only include what he needs for the functionality that he actually uses in a particular situation.

A good example of including a specific header file rather than a general header file would be in the Boost type_traits library. The generalized Boost type_traits header is <boost/type_traits.hpp>. This header includes all the individual type traits headers, just as the C++ standard library the <type_traits> header includes all type traits. On the Boost side, however, it is possible to include header files for only the individual type traits being used in a TU instead of all type traits. When using the type_traits mod header the general C++ type_traits header is always included automatically. To have finer control over individual type traits header inclusion a programmer could use the low-level implementation header for type_traits and then manually include only the individual header file he is actually using when Boost is chosen as the dual library. The code might look like this:

#include <boost/cxx_dual/impl/type_traits.hpp>

#if CXXD_HAS_STD_TYPE_TRAITS
#include CXXD_TYPE_TRAITS_HEADER
#else
#include <boost/type_traits/add_const.hpp>
#endif

void SomeFunction()
    {
    // Code using CXXD_TYPE_TRAITS_NS::add_const
    }
Referring to dual library constructs

When a mod header is included a namespace alias is created to refer to the constructs of that mod. The namespace alias merely uses the namespace macro for the dual library chosen to refer to that mod's namespace. For some programmers using a namespace alias might be overkill. They would rather use other more specific means to refer to some construct of the dual library chosen. For other programmers using a namespace alias is fine but they would rather use one reflecting their own naming preference rather than the name automatically created for any given mod header. Finally some programmers might decide to use the namespace macro directly rather than use a namespace alias at all. In any of the above cases the existence of a namespace macro can be used to create alternative means to refer to a dual library constructs.

Using a specific construct

Some programmers do not want to use a namespace in general in their code when they are using only specific constructs of a given library. In C++ you can do this with a using declaration:

#include <boost/cxx_dual/impl/type_traits.hpp>
#include CXXD_TYPE_TRAITS_HEADER
using CXXD_TYPE_TRAITS_NS::add_const;

void SomeFunction()
    {
    // Code using add_const
    }
Creating own's one namespace alias

When using the low-level header a programmer might want to create his own namespace alias for referring in general to the constructs of the dual library chosen. This could obviously also be done when using the mod header but the automatically created namespace alias would be an extra namespace alias in that case which might never be used.

An example of creating one's own namespace alias could be:

#include <boost/cxx_dual/impl/type_traits.hpp>
#include CXXD_TYPE_TRAITS_HEADER
namespace mylib_tt = CXXD_TYPE_TRAITS_NS ;

void SomeFunction()
    {
    // Code using mylib_tt::some_type_traits_construct
    }
Using the namespace macro directly

Of course a programmer could choose to use the namespace macro directly rather than use a namespace alias at all:

#include <boost/cxx_dual/impl/type_traits.hpp>
#include CXXD_TYPE_TRAITS_HEADER

void SomeFunction()
    {
    // Code using CXXD_TYPE_TRAITS_NS::some_type_traits_construct
    }
Implementing one-off code

You may just want to test whether or not the C++ standard library for a particular mod is supported or not, and write one-off code accordingly without using the CXXD dual library facility for the mod at all. While you could do this using a Boost Config macro the CXXD library provides a more regular syntactical naming convention for identifying whether a mod supports the C++ standard library or not:

#include <boost/cxx_dual/impl/type_traits.hpp>

#if CXXD_HAS_STD_TYPE_TRAITS
#include <type_traits>
void SomeFunctionUsingCppTypeTraits()
    {
    // Code using std::some_trait
    }
#endif

or:

#include <boost/cxx_dual/impl/type_traits.hpp>

#if !CXXD_HAS_STD_TYPE_TRAITS
#include <boost/type_traits.hpp>
void SomeFunctionUsingBoostTraits()
    {
    // Code using boost::some_trait
    }
#endif

PrevUpHomeNext