Type Traits that Transform One Type to Another

| Home | Libraries | People | FAQ | More

### Type Traits that Transform One Type to Another

The following templates transform one type to another, based upon some well-defined rule. Each template has a single member called `type` that is the result of applying the transformation to the template argument `T`.

Synopsis:

    template <class T>
    struct add_const;

    template <class T>
    struct add_cv;

    template <class T>
    struct add_pointer;

    template <class T>
    struct add_reference;

    template <class T>
    struct add_volatile;

    template <class T>
    struct decay;

    template <class T>
    struct floating_point_promotion;

    template <class T>
    struct integral_promotion;

    template <class T>
    struct make_signed;

    template <class T>
    struct make_unsigned;

    template <class T>
    struct promote;

    template <class T>
    struct remove_all_extents;

    template <class T>
    struct remove_const;

    template <class T>
    struct remove_cv;

    template <class T>
    struct remove_extent;

    template <class T>
    struct remove_pointer;

    template <class T>
    struct remove_reference;

    template <class T>
    struct remove_volatile;

##### Broken Compiler Workarounds:

For all of these templates support for partial specialization of class templates is required to correctly implement the transformation. On the other hand, practice shows that many of the templates from this category are very useful, and often essential for implementing some generic libraries. Lack of these templates is often one of the major limiting factors in porting those libraries to compilers that do not yet support this language feature. As some of these compilers are going to be around for a while, and at least one of them is very wide-spread, it was decided that the library should provide workarounds where possible.

The basic idea behind the workaround is to manually define full specializations of all type transformation templates for all fundamental types, and all their 1st and 2nd rank cv-[un]qualified derivative pointer types, and to provide a user-level macro that will define all the explicit specializations needed for any user-defined type T.

The first part guarantees the successful compilation of something like this:

    BOOST_STATIC_ASSERT((is_same<char, remove_reference<char&>::type>::value));
    BOOST_STATIC_ASSERT((is_same<char const, remove_reference<char const&>::type>::value));
    BOOST_STATIC_ASSERT((is_same<char volatile, remove_reference<char volatile&>::type>::value));
    BOOST_STATIC_ASSERT((is_same<char const volatile, remove_reference<char const volatile&>::type>::value));
    BOOST_STATIC_ASSERT((is_same<char*, remove_reference<char*&>::type>::value));
    BOOST_STATIC_ASSERT((is_same<char const*, remove_reference<char const*&>::type>::value));
    ...
    BOOST_STATIC_ASSERT((is_same<char const volatile* const volatile* const volatile, remove_reference<char const volatile* const volatile* const volatile&>::type>::value));

and the second part provides the library's users with a mechanism to make the above code work not only for `char`, `int` or other built-in type, but for their own types as well:

    namespace myspace{
       struct MyClass {};
    }
    // declare this at global scope:
    BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(myspace::MyClass)
    // transformations on myspace::MyClass now work:
    BOOST_STATIC_ASSERT((is_same<myspace::MyClass, remove_reference<myspace::MyClass&>::type>::value));
    BOOST_STATIC_ASSERT((is_same<myspace::MyClass, remove_const<myspace::MyClass const>::type>::value));
    // etc.

Note that the macro BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates to nothing on those compilers that do support partial specialization.