Header <boost/type_traits.hpp>

The contents of <boost/type_traits.hpp> are declared in namespace boost.

The file <boost/type_traits.hpp> contains various template classes that describe the fundamental properties of a type; each class represents a single type property or a single type transformation. If you are new to this library then read the accompanying article first.

This documentation is divided up into the following sections:

Primary Type Categorisation
Secondary Type Categorisation
Type Properties
Relationships Between Types
Transformations Between Types
Compiler Support Information
Type traits headers
Example Code

All of the integral expressions in this library are integral constant expressions, these can sometimes cause compiler problems in use, so there is a related set of coding guidelines to help you write portable code using this library.

Primary Type Categorisation

The following type traits templates identify which type category the type belongs to. For any given type, exactly one of the following expressions will evaluate to true. Note that this means that is_integral<T>::value and is_float<T>::value will only every be true for built-in types; if you want to check for a user-defined type that may behave "as if" it is an integral or floating point type, then use the std::numeric_limits template instead.

 

Expression

Description

Reference

Compiler requirements

 
  ::boost::is_void<T>::value Evaluates to true only if T is a cv-qualified void type.

3.9.1p9

   
  ::boost::is_integral<T>::value Evaluates to true only if T is an cv-qualified integral type.

3.9.1p7

   
  ::boost::is_float<T>::value Evaluates to true only if T is a cv-qualified floating point type.

3.9.1p8

   
  ::boost::is_pointer<T>::value Evaluates to true only if T is cv-qualified pointer type (includes function pointers, but excludes pointers to members).

3.9.2p2

8.3.1

   
  ::boost::is_reference<T>::value Evaluates to true only if T is a reference type.

3.9.2

8.3.2

If the compiler does not support partial-specialization of class templates, then references to types that are both const and volatile qualified will not be correctly identified.  
  ::boost::is_member_pointer<T>::value Evaluates to true only if T is a cv-qualified pointer to a data-member or member-function.

3.9.2

8.3.3

On some compilers, member function pointers may be incorrectly identified as regular pointers.  
  ::boost::is_array<T>::value Evaluates to true only if T is an array type.

3.9.2

8.3.4

If the compiler does not support partial-specialization of class templates, then some types may be incorrectly identified as arrays (mainly function types).  
  ::boost::is_union<T>::value Evaluates to true only if T is of union type. Currently requires some kind of compiler support, otherwise unions are identified as classes.

3.9.2

9.5

C  
  ::boost::is_class<T>::value Evaluates to true only if T is of class/struct type.

3.9.2

9.2

C  
  ::boost::is_enum<T>::value Evaluates to true only if T is of enum type.

3.9.2

7.2

Requires a correctly functioning is_convertible template (this means that is_enum is currently broken under Borland C++).  
  ::boost::is_function<T>::value Evaluates to true only if T is a function type (note not a reference or pointer to function).

3.9.2p1

8.3.5

Without partial specialisation support, this template does not compile for reference types.  

 

Secondary Type Categorisation

The following type categories are made up of the union of one or more primary type categorisations. A type may belong to more than one of these categories, in addition to one of the primary categories.

 

Expression

Description

Reference

Compiler requirements

 
  ::boost::is_arithmetic<T>::value Evaluates to true only if T is a cv-qualified arithmetic type. That is either an integral or floating point type.

3.9.1p8

   
  ::boost::is_fundamental<T>::value Evaluates to true only if T is an cv-qualified fundamental type. That is either an integral, a floating point, or a void type.

3.9.1

   
  ::boost::is_object<T>::value Evaluates to true only if T is a cv-qualified object type. That is not a function, reference, or void type.

3.9p9

   
  ::boost::is_scalar<T>::value Evaluates to true only if T is cv-qualified scalar type. That is an arithmetic, a pointer or a pointer to member type.

3.9p10

   
  ::boost::is_compound<T>::value Evaluates to true only if T is a compound type. That is an array, function, pointer, reference, enumerator, union, class or member function type.

3.9.2

   

 

Type Properties

The following templates identify the properties that a type has.

 

Expression

Description

Reference

Compiler requirements

 
  ::boost::alignment_of<T>::value Identifies the alignment requirements of T. Actually returns a value that is only guaranteed to be a multiple of the actual alignment requirements of T      
  ::boost::is_empty<T>::value True if T is an empty struct or class. If the compiler implements the "zero sized empty base classes" optimisation, then is_empty will correctly guess whether T is empty. Relies upon is_class to determine whether T is a class type.

10p5

PCD

 
  ::boost::is_const<T>::value Evaluates to true only if T is top-level const-qualified.

3.9.3

   
  ::boost::is_volatile<T>::value Evaluates to true only if T is volatile-qualified.

3.9.3

   
  ::boost::is_POD<T>::value Evaluates to true only if T is a cv-qualified POD type.

3.9p10

9p4

   
  ::boost::has_trivial_constructor<T>::value True if T has a trivial default constructor - that is T() is equivalent to memset.  

PC

 
  ::boost::has_trivial_copy<T>::value True if T has a trivial copy constructor - that is T(const T&) is equivalent to memcpy.  

PC

 
  ::boost::has_trivial_assign<T>::value True if T has a trivial assignment operator - that is if T::operator=(const T&) is equivalent to memcpy.  

PC

 
  ::boost::has_trivial_destructor<T>::value True if T has a trivial destructor - that is if T::~T() has no effect.  

PC

 

 

Relationships Between Types

The following templates determine the whether there is a relationship between two types:

 

Expression

Description

Reference

Compiler requirements

 
 
::boost::is_same<T,U>::value

Evaluates to true if T and U are the same type.

     
  ::boost::is_convertible<T,U>::value Evaluates to true if type T is convertible to type U.

4

8.5

Note that this template is currently broken with Borland's compiler, for constructor-based conversions.  

 

Transformations Between Types

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:

 

Expression

Description

Reference

Compiler requirements

 
  ::boost::remove_const<T>::type Creates a type the same as T but with any top level const qualifier removed. For example "const int" would become "int", but "const int*" would remain unchanged. 3.9.3

P

 
  ::boost::remove_volatile<T>::type Creates a type the same as T but with any top level volatile qualifier removed. For example "volatile int" would become "int".

3.9.3

P

 
  ::boost::remove_cv<T>::type Creates a type the same as T but with any top level cv-qualifiers removed. For example "const volatile int" would become "int". 3.9.3

P

 
  ::boost::remove_reference<T>::type If T is a reference type then removes the reference, otherwise leaves T unchanged. For example "int&" becomes "int" but "int*" remains unchanged. 8.3.2

P

 
  ::boost::remove_bounds<T>::type If T is an array type then removes the top level array qualifier from T, otherwise leaves T unchanged. For example "int[2][3]" becomes "int[3]". 8.3.4

P

 
  ::boost::remove_pointer<T>::type If T is a pointer type, then removes the top-level indirection from T, otherwise leaves T unchanged. For example "int*" becomes "int", but "int&" remains unchanged. 8.3.1

P

 
  ::boost::add_reference<T>::type If T is a reference type then leaves T unchanged, otherwise converts T to a reference type. For example "int&" remains unchanged, but "double" becomes "double&". 8.3.2

P

 
  ::boost::add_pointer<T>::type If "t" is an instance of T, then add_pointer<T>::type is the type returned by "&t". For example "int", "int&", "int[2]" and "int (&)[2]" all become "int*". 8.3.1

P

 
  ::boost::add_const<T>::type The same as "T const" for all T. 3.9.3    
  ::boost::add_volatile<T>::type The same as "T volatile" for all T. 3.9.3    

As the table above indicates, support for partial specialization of class templates is required to correctly implement the type transformation templates. 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

  1. 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
  2. Provide a user-level macro that will define such explicit specializations 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 library's users with a mechanism to make the above code work not only for 'char', 'int' or other built-in type, but for they own types too:

struct my {};
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(my)
BOOST_STATIC_ASSERT((is_same<my, remove_reference<my&>::type>::value));
BOOST_STATIC_ASSERT((is_same<my, remove_const<my 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.

Compiler Support Information

The legends used in the tables above have the following meanings:

P

Denotes that the class requires support for partial specialization of class templates to work correctly.

C

Denotes that direct compiler support for that traits class is required.

D

Denotes that the traits class is dependent upon a class that requires direct compiler support.

 

For those classes that are marked with a D or C, if compiler support is not provided, this type trait may return "false" when the correct value is actually "true". The single exception to this rule is "is_class", which attempts to guess whether or not T is really a class, and may return "true" when the correct value is actually "false". This can happen if: T is a union or T is a compiler-supplied scalar type that is not specialised for in these type traits.

If there is no compiler support, to ensure that these traits always return the correct values, specialise 'is_union' for each user-defined union type, 'is_empty' for each user-defined empty composite type, and 'is_POD' for each user-defined POD type. The 'has_*' traits should also be specialized if the user-defined type has those traits and is not a POD.

The following rules are automatically enforced:

is_enum implies is_POD

is_POD implies has_*

This means, for example, if you have an empty POD-struct, just specialize is_empty and is_POD, which will cause all the has_* to also return true.

Type Traits Headers

The type traits library is normally included with:

#include <boost/type_traits.hpp>

However the library is actually split up into a number of smaller headers, sometimes it can be convenient to include one of these directly in order to get just those type traits classes you actually need. Note however that the type traits classes are highly interdependent - so you may not save as much as you think this way. The following table lists the type traits classes in alphabetical order, along with the header that contains each template.

  Template class Header  
  add_const <boost/type_traits/transform_traits.hpp>  
  add_pointer <boost/type_traits/transform_traits.hpp>  
  add_reference <boost/type_traits/transform_traits.hpp>  
  add_volatile <boost/type_traits/transform_traits.hpp>  
  alignment_of <boost.type_traits/alignment_traits.hpp>  
  has_trivial_assign <boost/type_traits/object_traits.hpp>  
  has_trivial_constructor <boost/type_traits/object_traits.hpp>  
  has_trivial_copy <boost/type_traits/object_traits.hpp>  
  has_trivial_destructor <boost/type_traits/object_traits.hpp>  
  is_arithmetic <boost/type_traits/arithmetic_traits.hpp>  
  is_array <boost/type_traits/composite_traits.hpp>  
  is_class <boost/type_traits/object_traits.hpp>  
  is_compound <boost/type_traits/object_traits.hpp>  
  is_const <boost/type_traits/cv_traits.hpp>  
  is_convertible <boost/type_traits/conversion_traits.hpp>  
  is_empty <boost/type_traits/object_traits.hpp>  
  is_enum <boost/type_traits/composite_traits.hpp>  
  is_float <boost/type_traits/arithmetic_traits.hpp>  
  is_function <boost/type_traits/function_traits.hpp>  
  is_fundamental <boost/type_traits/arithmetic_traits.hpp>  
  is_integral <boost/type_traits/arithmetic_traits.hpp>  
  is_member_pointer <boost/type_traits/composite_traits.hpp>  
  is_object <boost/type_traits/object_traits.hpp>  
  is_POD <boost/type_traits/object_traits.hpp>  
  is_pointer <boost/type_traits/composite_traits.hpp>  
  is_reference <boost/type_traits/composite_traits.hpp>  
  is_same <boost/type_traits/same_traits.hpp>  
  is_scalar <boost/type_traits/object_traits.hpp>  
  is_union <boost/type_traits/composite_traits.hpp>  
  is_void <boost/type_traits/arithmetic_traits.hpp>  
  is_volatile <boost/type_traits/cv_traits.hpp>  
  remove_bounds <boost/type_traits/transform_traits.hpp>  
  remove_const <boost/type_traits/cv_traits.hpp>  
  remove_cv <boost/type_traits/cv_traits.hpp>  
  remove_pointer <boost/type_traits/transform_traits.hpp>  
  remove_reference <boost/type_traits/transform_traits.hpp>  
  remove_volatile <boost/type_traits/cv_traits.hpp>  

 

Example code

Type-traits comes with four example programs that illustrate some of the ways in which the type traits templates may be used:

Copy_example.cpp

Demonstrates a version of std::copy that uses memcpy where appropriate to optimise the copy operation;

//
// opt::copy
// same semantics as std::copy
// calls memcpy where appropiate.
//

namespace detail{

template<typename I1, typename I2>
I2 copy_imp(I1 first, I1 last, I2 out)
{
   while(first != last)
   {
      *out = *first;
      ++out;
      ++first;
   }
   return out;
}

template <bool b>
struct copier
{
   template<typename I1, typename I2>
   static I2 do_copy(I1 first, I1 last, I2 out)
   { return copy_imp(first, last, out); }
};

template <>
struct copier<true>
{
   template<typename I1, typename I2>
   static I2* do_copy(I1* first, I1* last, I2* out)
   {
      memcpy(out, first, (last-first)*sizeof(I2));
      return out+(last-first);
   }
};


}

template<typename I1, typename I2>
inline I2 copy(I1 first, I1 last, I2 out)
{
   typedef typename boost::remove_cv<typename std::iterator_traits<I1>::value_type>::type v1_t;
   typedef typename boost::remove_cv<typename std::iterator_traits<I2>::value_type>::type v2_t;
   return detail::copier<
      ::boost::type_traits::ice_and<
         ::boost::is_same<v1_t, v2_t>::value,
         ::boost::is_pointer<I1>::value,
         ::boost::is_pointer<I2>::value,
         ::boost::has_trivial_assign<v1_t>::value
      >::value>::do_copy(first, last, out);
}

fill_example.cpp

Demonstrates a version of std::fill that uses memset where appropriate to optimise fill operations. Also uses call_traits to optimise parameter passing, to avoid aliasing issues:

namespace opt{
//
// fill
// same as std::fill, uses memset where appropriate, along with call_traits
// to "optimise" parameter passing.
//
namespace detail{

template <typename I, typename T>
void do_fill_(I first, I last, typename boost::call_traits<T>::param_type val)
{
   while(first != last)
   {
      *first = val;
      ++first;
   }
}

template <bool opt>
struct filler
{
   template <typename I, typename T>
   struct rebind
   {
      static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
      { do_fill_<I,T>(first, last, val); }
   };
};

template <>
struct filler<true>
{
   template <typename I, typename T>
   struct rebind
   {
      static void do_fill(I first, I last, T val)
      {
         std::memset(first, val, last-first);
      }
   };
};

}

template <class I, class T>
inline void fill(I first, I last, const T& val)
{
   typedef detail::filler<
      ::boost::type_traits::ice_and<
         ::boost::is_pointer<I>::value,
         ::boost::is_arithmetic<T>::value,
         (sizeof(T) == 1)
      >::value> filler_t;
   typedef typename filler_t:: template rebind<I,T> binder;
   binder::do_fill(first, last, val);
}

};   // namespace opt

iter_swap_example.cpp

Demonstrates a version of std::iter_swap that works with proxying iterators, as well as regular ones; calls std::swap for regular iterators, otherwise does a "slow but safe" swap:

namespace opt{
//
// iter_swap:
// tests whether iterator is a proxying iterator or not, and
// uses optimal form accordingly:
//
namespace detail{

template <bool b>
struct swapper
{
   template <typename I>
   static void do_swap(I one, I two)
   {
      typedef typename std::iterator_traits<I>::value_type v_t;
      v_t v = *one;
      *one = *two;
      *two = v;
   }
};

template <>
struct swapper<true>
{
   template <typename I>
   static void do_swap(I one, I two)
   {
      using std::swap;
      swap(*one, *two);
   }
};

}

template <typename I1, typename I2>
inline void iter_swap(I1 one, I2 two)
{
   typedef typename std::iterator_traits<I1>::reference r1_t;
   typedef typename std::iterator_traits<I2>::reference r2_t;
   detail::swapper<
      ::boost::type_traits::ice_and<
         ::boost::is_reference<r1_t>::value, 
         ::boost::is_reference<r2_t>::value,
         ::boost::is_same<r1_t, r2_t>::value
      >::value>::do_swap(one, two);
}

};   // namespace opt

Trivial_destructor_example.cpp

This algorithm is the reverse of std::unitialized_copy; it takes a block of initialized memory and calls destructors on all objects therein. This would typically be used inside container classes that manage their own memory:

namespace opt{
//
// algorithm destroy_array:
// The reverse of std::unitialized_copy, takes a block of
// initialized memory and calls destructors on all objects therein.
//

namespace detail{

template <bool>
struct array_destroyer
{
   template <class T>
   static void destroy_array(T* i, T* j){ do_destroy_array(i, j); }
};

template <>
struct array_destroyer<true>
{
   template <class T>
   static void destroy_array(T*, T*){}
};

template <class T>
void do_destroy_array(T* first, T* last)
{
   while(first != last)
   {
      first->~T();
      ++first;
   }
}

}; // namespace detail

template <class T>
inline void destroy_array(T* p1, T* p2)
{
   detail::array_destroyer<boost::has_trivial_destructor<T>::value>::destroy_array(p1, p2);
}
} // namespace opt

Revised 22 April 2001

Documentation © Copyright John Maddock 2001. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.

The type traits library is based on contributions by Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat Marcus, John Maddock and Jeremy Siek.

Mat Marcus and Jesse Jones have worked on, and published a paper describing the partial specialisation workarounds used in this library.

The is_convertible template is based on code originally devised by Andrei Alexandrescu, see "Generic<Programming>: Mappings between Types and Values".

Maintained by John Maddock, the latest version of this file can be found at www.boost.org, and the boost discussion list at www.yahoogroups.com/list/boost.