From 7c8c40f0fa46e50beb58385940ae5df2b93bebeb Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sun, 24 Apr 2005 12:01:56 +0000 Subject: [PATCH] Fix up docs to point to new BoostBook versions. [SVN r28460] --- cxx_type_traits.htm | 601 +-------------------- index.html | 1241 +------------------------------------------ 2 files changed, 26 insertions(+), 1816 deletions(-) diff --git a/cxx_type_traits.htm b/cxx_type_traits.htm index 59f188d..28f1073 100644 --- a/cxx_type_traits.htm +++ b/cxx_type_traits.htm @@ -1,590 +1,15 @@ + - - - - - -C++ Type traits - - - - -

C++ Type traits

- -

by John Maddock and Steve Cleary

- -

This is the draft version of an article -that appeared in the October 2000 issue of Dr Dobb's Journal

- -

Generic programming (writing code which works with any data -type meeting a set of requirements) has become the method of -choice for providing reusable code. However, there are times in -generic programming when "generic" just isn't good -enough - sometimes the differences between types are too large -for an efficient generic implementation. This is when the traits -technique becomes important - by encapsulating those properties -that need to be considered on a type by type basis inside a -traits class, we can minimise the amount of code that has to -differ from one type to another, and maximise the amount of -generic code.

- -

Consider an example: when working with character strings, one -common operation is to determine the length of a null terminated -string. Clearly it's possible to write generic code that can do -this, but it turns out that there are much more efficient methods -available: for example, the C library functions strlen and wcslen are usually written in assembler, -and with suitable hardware support can be considerably faster -than a generic version written in C++. The authors of the C++ -standard library realised this, and abstracted the properties of char and wchar_t into the class char_traits. Generic code that works -with character strings can simply use char_traits<>::length to -determine the length of a null terminated string, safe in the -knowledge that specialisations of char_traits will use the most -appropriate method available to them.

- -

Type traits

- -

Class char_traits is -a classic example of a collection of type specific properties -wrapped up in a single class - what Nathan Myers termed a baggage -class[1]. In the Boost type-traits library, we[2] have -written a set of very specific traits classes, each of which -encapsulate a single trait from the C++ type system; for example, -is a type a pointer or a reference type? Or does a type have a -trivial constructor, or a const-qualifier? The type-traits -classes share a unified design: each class has a single member value, -a compile-time constant that is true if the type has the -specified property, and false otherwise. As we will show, these -classes can be used in generic programming to determine the -properties of a given type and introduce optimisations that are -appropriate for that case.

- -

The type-traits library also contains a set of classes that -perform a specific transformation on a type; for example, they -can remove a top-level const or volatile qualifier from a type. -Each class that performs a transformation defines a single -typedef-member type that is the result of the -transformation. All of the type-traits classes are defined inside -namespace boost; for -brevity, namespace-qualification is omitted in most of the code -samples given.

- -

Implementation

- -

There are far too many separate classes contained in the type-traits -library to give a full implementation here - see the source code -in the Boost library for the full details - however, most of the -implementation is fairly repetitive anyway, so here we will just -give you a flavour for how some of the classes are implemented. -Beginning with possibly the simplest class in the library, is_void<T> -has a member value that is true only if T is void.

- -
template <typename T> 
-struct is_void
-{ static const bool value = false; };
-
-template <> 
-struct is_void<void>
-{ static const bool value = true; };
- -

Here we define a primary version of the template class is_void, and provide a full-specialisation -when T is void. While full specialisation of a template class is -an important technique, sometimes we need a solution that is -halfway between a fully generic solution, and a full -specialisation. This is exactly the situation for which the -standards committee defined partial template-class specialisation. -As an example, consider the class boost::is_pointer<T>: -here we needed a primary version that handles all the cases where -T is not a pointer, and a partial specialisation to handle all -the cases where T is a pointer:

- -
template <typename T> 
-struct is_pointer 
-{ static const bool value = false; };
-
-template <typename T> 
-struct is_pointer<T*> 
-{ static const bool value = true; };
- -

The syntax for partial specialisation is somewhat arcane and -could easily occupy an article in its own right; like full -specialisation, in order to write a partial specialisation for a -class, you must first declare the primary template. The partial -specialisation contains an extra <…> after the class -name that contains the partial specialisation parameters; these -define the types that will bind to that partial specialisation -rather than the default template. The rules for what can appear -in a partial specialisation are somewhat convoluted, but as a -rule of thumb if you can legally write two function overloads of -the form:

- -
void foo(T);
-void foo(U);
- -

Then you can also write a partial specialisation of the form:

- -
template <typename T>
-class c{ /*details*/ };
-
-template <typename T>
-
-class c<U>{ /*details*/ };
- -

This rule is by no means foolproof, but it is reasonably -simple to remember and close enough to the actual rule to be -useful for everyday use.

- -

As a more complex example of partial specialisation consider -the class remove_bounds<T>. This class defines a single -typedef-member type that is the same type as T but with -any top-level array bounds removed; this is an example of a -traits class that performs a transformation on a type:

- -
template <typename T> 
-struct remove_bounds
-{ typedef T type; };
-
-template <typename T, std::size_t N> 
-struct remove_bounds<T[N]>
-{ typedef T type; };
- -

The aim of remove_bounds is this: imagine a generic algorithm -that is passed an array type as a template parameter, remove_bounds provides a means -of determining the underlying type of the array. For example remove_bounds<int[4][5]>::type -would evaluate to the type int[5]. This example also -shows that the number of template parameters in a partial -specialisation does not have to match the number in the default -template. However, the number of parameters that appear after the -class name do have to match the number and type of the parameters -in the default template.

- -

Optimised copy

- -

As an example of how the type traits classes can be used, -consider the standard library algorithm copy:

- -
template<typename Iter1, typename Iter2>
-Iter2 copy(Iter1 first, Iter1 last, Iter2 out);
- -

Obviously, there's no problem writing a generic version of -copy that works for all iterator types Iter1 and Iter2; however, -there are some circumstances when the copy operation can best be -performed by a call to memcpy. -In order to implement copy in terms of memcpy all of the following conditions -need to be met:

- - - -

By trivial assignment operator we mean that the type is either -a scalar type[3] or:

- - - -

If all these conditions are met then a type can be copied -using memcpy rather than -using a compiler generated assignment operator. The type-traits -library provides a class has_trivial_assign, such that has_trivial_assign<T>::value -is true only if T has a trivial assignment operator. This class -"just works" for scalar types, but has to be explicitly -specialised for class/struct types that also happen to have a -trivial assignment operator. In other words if has_trivial_assign -gives the wrong answer, it will give the "safe" wrong -answer - that trivial assignment is not allowable.

- -

The code for an optimised version of copy that uses memcpy where appropriate is -given in listing 1. The code begins by defining a template class copier, -that takes a single Boolean template parameter, and has a static -template member function do_copy -which performs the generic version of copy -(in other words the "slow but safe version"). Following -that there is a specialisation for copier<true>: -again this defines a static template member function do_copy, but this version uses -memcpy to perform an "optimised" copy.

- -

In order to complete the implementation, what we need now is a -version of copy, that calls copier<true>::do_copy -if it is safe to use memcpy, -and otherwise calls copier<false>::do_copy to -do a "generic" copy. This is what the version in -listing 1 does. To understand how the code works look at the code -for copy and consider -first the two typedefs v1_t and v2_t. These use std::iterator_traits<Iter1>::value_type -to determine what type the two iterators point to, and then feed -the result into another type-traits class remove_cv that -removes the top-level const-volatile-qualifiers: this will allow -copy to compare the two types without regard to const- or -volatile-qualifiers. Next, copy -declares an enumerated value can_opt that will become the -template parameter to copier - declaring this here as a constant -is really just a convenience - the value could be passed directly -to class copier. The -value of can_opt is computed by verifying that all of the -following are true:

- - - -

Finally we can use the value of can_opt as the template -argument to copier - this version of copy will now adapt to -whatever parameters are passed to it, if its possible to use memcpy, then it will do so, -otherwise it will use a generic copy.

- -

Was it worth it?

- -

It has often been repeated in these columns that "premature -optimisation is the root of all evil" [4]. So the question -must be asked: was our optimisation premature? To put this in -perspective the timings for our version of copy compared a -conventional generic copy[5] are shown in table 1.

- -

Clearly the optimisation makes a difference in this case; but, -to be fair, the timings are loaded to exclude cache miss effects -- without this accurate comparison between algorithms becomes -difficult. However, perhaps we can add a couple of caveats to the -premature optimisation rule:

- - - -

Table 1: Time taken to copy 1000 elements using copy<const -T*, T*> (times in micro-seconds)

- - - - - - - - - - - - - - - - - - - - - - - - - - - -

Version

-

T

-

Time

-
"Optimised" copychar0.99
Conventional copychar8.07
"Optimised" copyint2.52
Conventional copyint8.02
- -

 

- -

Pair of References

- -

The optimised copy example shows how type traits may be used -to perform optimisation decisions at compile-time. Another -important usage of type traits is to allow code to compile that -otherwise would not do so unless excessive partial specialization -is used. This is possible by delegating partial specialization to -the type traits classes. Our example for this form of usage is a -pair that can hold references [6].

- -

First, let us examine the definition of "std::pair", -omitting the comparision operators, default constructor, and -template copy constructor for simplicity:

- -
template <typename T1, typename T2> 
-struct pair 
-{
-  typedef T1 first_type;
-  typedef T2 second_type;
-
-  T1 first;
-  T2 second;
-
-  pair(const T1 & nfirst, const T2 & nsecond)
-  :first(nfirst), second(nsecond) { }
-};
- -

Now, this "pair" cannot hold references as it -currently stands, because the constructor would require taking a -reference to a reference, which is currently illegal [7]. Let us -consider what the constructor's parameters would have to be in -order to allow "pair" to hold non-reference types, -references, and constant references:

- - - - - - - - - - - - - - - - - - -
Type of "T1"Type of parameter to - initializing constructor
T
-
const T &
-
T &
-
T &
-
const T &
-
const T &
-
- -

A little familiarity with the type traits classes allows us to -construct a single mapping that allows us to determine the type -of parameter from the type of the contained class. The type -traits classes provide a transformation "add_reference", -which adds a reference to its type, unless it is already a -reference.

- - - - - - - - - - - - - - - - - - - - - - -
Type of "T1"Type of "const T1"Type of "add_reference<const - T1>::type"
T
-
const T
-
const T &
-
T &
-
T & [8]
-
T &
-
const T &
-
const T &
-
const T &
-
- -

This allows us to build a primary template definition for -"pair" that can contain non-reference types, reference -types, and constant reference types:

- -
template <typename T1, typename T2> 
-struct pair 
-{
-  typedef T1 first_type;
-  typedef T2 second_type;
-
-  T1 first;
-  T2 second;
-
-  pair(boost::add_reference<const T1>::type nfirst,
-       boost::add_reference<const T2>::type nsecond)
-  :first(nfirst), second(nsecond) { }
-};
- -

Add back in the standard comparision operators, default -constructor, and template copy constructor (which are all the -same), and you have a std::pair that can hold reference types!

- -

This same extension could have been done using partial -template specialization of "pair", but to specialize -"pair" in this way would require three partial -specializations, plus the primary template. Type traits allows us -to define a single primary template that adjusts itself auto-magically -to any of these partial specializations, instead of a brute-force -partial specialization approach. Using type traits in this -fashion allows programmers to delegate partial specialization to -the type traits classes, resulting in code that is easier to -maintain and easier to understand.

- -

Conclusion

- -

We hope that in this article we have been able to give you -some idea of what type-traits are all about. A more complete -listing of the available classes are in the boost documentation, -along with further examples using type traits. Templates have -enabled C++ uses to take the advantage of the code reuse that -generic programming brings; hopefully this article has shown that -generic programming does not have to sink to the lowest common -denominator, and that templates can be optimal as well as generic.

- -

Acknowledgements

- -

The authors would like to thank Beman Dawes and Howard Hinnant -for their helpful comments when preparing this article.

- -

References

- -
    -
  1. Nathan C. Myers, C++ Report, June 1995.
  2. -
  3. The type traits library is based upon contributions by - Steve Cleary, Beman Dawes, Howard Hinnant and John - Maddock: it can be found at www.boost.org.
  4. -
  5. A scalar type is an arithmetic type (i.e. a built-in - integer or floating point type), an enumeration type, a - pointer, a pointer to member, or a const- or volatile-qualified - version of one of these types.
  6. -
  7. This quote is from Donald Knuth, ACM Computing Surveys, - December 1974, pg 268.
  8. -
  9. The test code is available as part of the boost utility - library (see algo_opt_examples.cpp), the code was - compiled with gcc 2.95 with all optimisations turned on, - tests were conducted on a 400MHz Pentium II machine - running Microsoft Windows 98.
  10. -
  11. John Maddock and Howard Hinnant have submitted a "compressed_pair" - library to Boost, which uses a technique similar to the - one described here to hold references. Their pair also - uses type traits to determine if any of the types are - empty, and will derive instead of contain to conserve - space -- hence the name "compressed".
  12. -
  13. This is actually an issue with the C++ Core Language - Working Group (issue #106), submitted by Bjarne - Stroustrup. The tentative resolution is to allow a "reference - to a reference to T" to mean the same thing as a - "reference to T", but only in template - instantiation, in a method similar to multiple cv-qualifiers.
  14. -
  15. For those of you who are wondering why this shouldn't be - const-qualified, remember that references are always - implicitly constant (for example, you can't re-assign a - reference). Remember also that "const T &" - is something completely different. For this reason, cv-qualifiers - on template type arguments that are references are - ignored.
  16. -
- -

Listing 1

- -
namespace detail{
-
-template <bool b>
-struct copier
-{
-   template<typename I1, typename I2>
-   static I2 do_copy(I1 first, 
-                     I1 last, I2 out);
-};
-
-template <bool b>
-template<typename I1, typename I2>
-I2 copier<b>::do_copy(I1 first, 
-                      I1 last, 
-                      I2 out)
-{
-   while(first != last)
-   {
-      *out = *first;
-      ++out;
-      ++first;
-   }
-   return 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;
-
-   enum{ can_opt = 
-      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 
-   };
-
-   return detail::copier<can_opt>::
-      do_copy(first, last, out);
-}
- -
- -

© Copyright John Maddock and Steve Cleary, 2000

- + + + + + Automatic redirection failed, please go to + ../../doc/html/boost_typetraits/background.html + or view the online version at + http://www.boost.org/regression-logs/cs-win32_metacomm/doc/html/boost_typetraits/background.html + + + + diff --git a/index.html b/index.html index 989eeb2..1180f8b 100644 --- a/index.html +++ b/index.html @@ -1,1230 +1,15 @@ + - - Type Traits - - - - - -

Header <boost/type_traits.hpp>

-

Contents

-
Introduction
-Primary Type Categorisation
-Secondary Type Categorisation
-Type Properties
-Relationships Between Types
-Transformations Between Types
-Synthesizing Types
-Function Traits
-Type traits headers
User defined specializations -Example Code
-

Introduction

-

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

-

The file <boost/type_traits.hpp> - defines three kinds of type trait:

-
    -
  1. - The properties of a specific type. -
  2. - The relationship between two types. -
  3. - A transformation from one type to another.
  4. -
-

If you are new to this library then the accompanying - article provides the background information and motivation.

-

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_floating_point<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>::valueEvaluates to true only if T is a - cv-qualified void type.

3.9.1p9

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

3.9.1p7

-
  
 ::boost::is_floating_point<T>::valueEvaluates to true only if T is a - cv-qualified floating point type.

3.9.1p8

-
  
 ::boost::is_pointer<T>::valueEvaluates 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>::valueEvaluates 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 this template may report the - wrong result for function types. 
 ::boost::is_member_pointer<T>::valueEvaluates to true only if T is a - cv-qualified pointer to a data-member or member-function.

3.9.2

-

8.3.3

-
  
 ::boost::is_array<T>::valueEvaluates 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 this template can give the - wrong result with function types. 
 ::boost::is_union<T>::valueEvaluates 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

-
Without (some as yet unspecified) - help from the compiler, we cannot distinguish between union and class types, as - a result this expression will never evaluate to true. 
 ::boost::is_class<T>::valueEvaluates to true only if T is of - class/struct type.

3.9.2

-

9.2

-
Without (some as yet unspecified) - help from the compiler, we cannot distinguish between union and class types, as - a result this expression will erroneously evaluate to true for union types. 
 ::boost::is_enum<T>::valueEvaluates 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++ Builder 5, and for the Metrowerks compiler prior to version 8, - other compilers should handle this template just fine. 
 ::boost::is_function<T>::valueEvaluates to true only if T is a function type - (note not a reference or pointer to function).

3.9.2p1

-

8.3.5

-
If the compiler does not support - partial-specialization of class templates, then 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>::valueEvaluates 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>::valueEvaluates 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>::valueEvaluates 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>::valueEvaluates to true only if T is - cv-qualified scalar type. That is an arithmetic, enumeration, pointer or a - pointer to member type.

3.9p10

-
If the compiler does not support - partial-specialization of class templates, then this template can not be used - with function types. 
 ::boost::is_compound<T>::value - Evaluates to true only if T is a compound type. (Any type that is not a - fundamental type is a compound type).

3.9.2

-
 
 ::boost::is_member_function_pointer<T>::valueEvaluates to true only if T is a pointer to a member - function (and not a pointer to a member object). This template splits - is_member_pointer into two sub-categories.

3.9.2

-

8.3.3

-
  
::boost::is_member_object_pointer<T>::valueEvaluates to true only if T is a pointer to a member - object(and not a pointer to a member function). This template splits - is_member_pointer into two sub-categories. -

3.9.2

-

8.3.3

-
-

 

-

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.

-

T must be a complete type.

-
   
::boost::rank<T>::valueThe number of array dimentions in type T.  - Zero if T is not an array type.Requires partial specialisation of class - templates.
::boost::extent<T, std::size_t N = - 0>::valueThe number of elements in the N'th array bound - of T.  If T has fewer than N bounds, or if the N'th array bound is - incomplete, then zero.Requires partial specialisation of class - templates.
 ::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. -

-

T must be a complete type.

-

10p5

-

Relies on the compiler - implementing zero sized empty base classes in order to detect empty classes. -

-

Can not be used with incomplete types.

-

Can not be used with union types, until is_union can be made to - work.

-

If the compiler does not support partial-specialization of class - templates, then this template can not be used with abstract types.

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

3.9.3

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

3.9.3

-
  
::boost::is_abstract<T>::valueEvaluates true only if T is abstract class.10.3 -

Compiler must support DR337 (as Jan 2004: GCC 3.4, VC++ 7.1, Intel C++ 7, and - Comeau 4.3.2).

-

Otherwise produces the same value as is_polymorphic<T>::value; this is - the "safe fallback position" for which polymorphic types are - always regarded as potentially abstract.

-

The macro BOOST_NO_IS_ABSTRACT is used to signify that the implemention is - buggy, users should check for this in their own code if the "safe fallback" is - not suitable for their particular use-case.

-
 ::boost::is_polymorphic<T>::valueEvaluates to true only if T is a polymorphic - type. -

T must be a complete type.

-
10.3Requires knowledge of the compilers ABI, does - actually seem to work with the majority of compilers though. 
::boost::has_virtual_destructor<T>::valueShould evaluate to true whenever type T has a - virtual destructor: currently evaluates to false in all cases, unless - user-specialised.12.4There is currently no way to portably implement - this trait, the default version provided always evaluates to false, and has to - be explicity specialised for types with virtual destructors.
 ::boost::is_pod<T>::valueEvaluates to true only if T is a cv-qualified - POD type. -

T must be a complete type.

-

3.9p10

-

9p4

-
Without some (as yet unspecified) help from the - compiler, is_pod will never report that a class or struct is a POD; this is - always safe, if possibly sub-optimal.

If the compiler does not support - partial-specialization of class templates, then this template can not be used - with function types.

-
 
 ::boost::has_trivial_constructor<T>::valueTrue if T has a trivial default constructor.12.1p5

Without some (as yet unspecified) - help from the compiler, has_trivial_constructor will never report - that a class or struct has a trivial constructor; this is always safe, if - possibly sub-optimal.

-

If the compiler does not support partial-specialization of class templates, - then this template can not be used with function types.

-
 
 ::boost::has_trivial_copy<T>::valueTrue if T has a trivial copy constructor. -

T must be a complete type.

-
12.8p6

Without some (as yet unspecified) - help from the compiler, has_trivial_copy will never report that a - class or struct has a trivial copy constructor; this is always safe, if - possibly sub-optimal.

-

If the compiler does not support partial-specialization of class templates, - then this template can not be used with function types.

-
 
 ::boost::has_trivial_assign<T>::valueTrue if T has a trivial assignment operator. -

T must be a complete type.

-
12.8p11

Without some (as yet unspecified) - help from the compiler, has_trivial_assign will never report that - a class or struct has a trivial assignment operator; this is always safe, if - possibly sub-optimal.

-

If the compiler does not support partial-specialization of class templates, - then this template can not be used with function types.

-
 
 ::boost::has_trivial_destructor<T>::valueTrue if T has a trivial destructor. -

T must be a complete type.

-
12.4p3

Without some (as yet unspecified) - help from the compiler, has_trivial_destructor will never report - that a class or struct has a trivial destructor; this is always safe, if - possibly sub-optimal.

-

If the compiler does not support partial-specialization of class templates, - then this template can not be used with function types.

-
 
 ::boost::is_stateless<T>::valueTrue if T is stateless, meaning that T has no - storage and its constructors and destructors are trivial. -

T must be a complete type.

-
 

Without some (as yet unspecified) - help from the compiler, is_stateless will never report that a - class or struct is_stateless; this is always safe, if possibly sub-optimal.

-

Will report true only if all of the following also report true:

-
::boost::has_trivial_constructor<T>::value,
-::boost::has_trivial_copy<T>::value,
-::boost::has_trivial_destructor<T>::value,
-::boost::is_class<T>::value,
-::boost::is_empty<T>::value
-
-

If the compiler does not support partial-specialization of class templates, - then this template can not be used with function types.

-
 
 ::boost::has_nothrow_constructor<T>::valueTrue if T has a non-throwing default - constructor. -

T must be a complete type.

-
 

Without some (as yet - unspecified) help from the compiler, has_nothrow_constructor will - never report that a class or struct has a non-throwing constructor; this is - always safe, if possibly sub-optimal.

-

If the compiler does not support partial-specialization of class - templates, then this template can not be used with function types.

-
 
 ::boost::has_nothrow_copy<T>::valueTrue if T has a non-throwing copy constructor. -

T must be a complete type.

-
 

Without some (as yet - unspecified) help from the compiler, has_nothrow_copy will never - report that a class or struct has a non-throwing copy constructor; this is - always safe, if possibly sub-optimal.

-

If the compiler does not support partial-specialization of class - templates, then this template can not be used with function types.

-
 
 ::boost::has_nothrow_assign<T>::valueTrue if T has a non-throwing assignment - operator. -

T must be a complete type.

-
 

Without some (as yet - unspecified) help from the compiler, has_nothrow_assign will never - report that a class or struct has a non-throwing assignment operator; this is - always safe, if possibly sub-optimal.

-

If the compiler does not support partial-specialization of class - templates, then this template can not be used with function types.

-
 
-

 

-

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.

-
 If the compiler does not support - partial-specialization of class templates, then this template can not be used - with abstract, incomplete or function types. 
 ::boost::is_convertible<T,U>::valueEvaluates to true if an imaginary - lvalue of type T is convertible to type U.

Type T must not be an incomplete - type.

-

Type U must not be an incomplete, abstract or function type.

-

No types are considered to be convertible to an array type.

-

4

-

8.5

-
Note that this template is - currently broken with Borland C++ Builder 5 (and earlier), for - constructor-based conversions, and for the Metrowerks 7 (and earlier) compiler - in all cases. 
 ::boost::is_base_of<T,U>::valueEvaluates to true if type T is a base class to type U.

Will - detect non-public base classes, and ambiguous base classes.

-

Note that a class is not considered to be it's own base class, likewise, if - either T or U are non-class types, then the result will always be false.

-

Types T and U must not be incomplete types.

-
10

If the compiler does not support - partial-specialization of class templates, then this template can not be used - with function types.

-
 
-

Note that both is_convertible, and is_base_of can - produce compiler errors if the convertion is ambiguous:

-
struct A {};
-struct B : A {};
-struct C : A {};
-struct D : B, C {};
-bool const x = boost::is_base_of<A,D>::value;  // error
-bool const y = boost::is_convertible<D*,A*>::value;     // error
-
-

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>::typeCreates 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

If the compiler does not support - partial-specialization of class templates, then this template will compile, but - will have no effect, except where noted below.

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

3.9.3

-

If the compiler does not support - partial-specialization of class templates, then this template will compile, but - will have no effect, except where noted below.

-
 
 ::boost::remove_cv<T>::typeCreates 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

If the compiler does not support - partial-specialization of class templates, then this template will compile, but - will have no effect, except where noted below.

-
 
 ::boost::remove_reference<T>::typeIf 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

If the compiler does not support - partial-specialization of class templates, then this template will compile, but - will have no effect, except where noted below.

-
 
 ::boost::remove_extent<T>::typeIf 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

If the compiler does not support - partial-specialization of class templates, then this template will compile, but - will have no effect.

-
 
::boost::remove_all_extents<T>::typeIf T is an array type then removes - the all the array qualifiers from T, otherwise leaves T unchanged. For example - "int[2][3]" becomes "int".8.3.4 -

If the compiler does not support partial-specialization of class - templates, then this template will compile, but will have no effect.

-
 ::boost::remove_pointer<T>::typeIf 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

If the compiler does not support - partial-specialization of class templates, then this template will compile, but - will have no effect, except where noted below.

-
 
 ::boost::add_reference<T>::typeIf 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  
 ::boost::add_pointer<T>::typeA type that is the same as - - - remove_reference<T>::type*. - For example "int" and "int&" both become "int*".8.3.1

If the compiler does not support - partial-specialization of class templates, then this template will not compile - with reference types.

-
 
 ::boost::add_const<T>::typeThe same as "T const" for all T.3.9.3  
 ::boost::add_volatile<T>::typeThe same as "T volatile" for all T.3.9.3  
 ::boost::add_cv<T>::typeThe same as "T const 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.
  3. -
-

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.

-

Synthesizing Types

-

The following template synthesizes a type with the desired properties. -

- - - - - - - - - - - - - - - - - - - - - - - - - -
 

Expression

-

Description

-

Reference

-

Compiler - requirements

-
 
 ::boost::type_with_alignment<Align>::typeAttempts to find a built-in or POD - type with an alignment that is a multiple of Align. -    
::boost::aligned_storage<Size,Align>::typeAttempts to find a POD type of size - Size, and alignment Align.
-

Function Traits

-

The ::boost::function_traits class template extracts information - from function types. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 

Expression

-

Description

-

Reference

-

Compiler - requirements

-
 
 ::boost::function_traits<F>::arityDetermine the arity of the function - type F. -  Without partial specialisation support, this - template does not compile for reference types. 
 ::boost::function_traits<F>::result_typeThe type returned by function type - F. -  Does not compile without support for partial - specialization of class templates. 
 ::boost::function_traits<F>::argN_typeThe Nth - argument type of function type F, where 1<=N<=arity - of F. Does not compile without support for partial - specialization of class templates. 
-

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.  The split headers - always have the same name as the template you require, and are located in - boost/type_traits/.  So if for example some code requires - is_class<>, then just include:

-
<boost/type_traits/is_class.hpp>
-

User defined specializations

-

Occationally the end user may need to provide their own specialization for one - of the type traits - typically where intrinsic compiler support is required to - implement a specific trait fully.  These specializations should derive - from boost::mpl::true_ or boost::mpl::false_ as appropriate:

-
#  include <boost/type_traits/is_pod.hpp>
-#  include <boost/type_traits/is_class.hpp>
-#  include <boost/type_traits/is_union.hpp>
-
-struct my_pod{};
-struct my_union
-{
-   char c;
-   int i;
-};
-
-namespace boost
-{
-template<>
-struct is_pod<my_pod> 
-   : public mpl::true_{};
-template<>
-struct is_pod<my_union> 
-   : public mpl::true_{};
-template<>
-struct is_union<my_union> 
-   : public mpl::true_{};
-template<>
-struct is_class<my_union> 
-   : public mpl::false_{};
-}
-
-      
-

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 boost@lists.boost.org - (see http://www.boost.org/more/mailing_lists.htm#main).

- + + + + + Automatic redirection failed, please go to + ../../doc/html/boost_typetraits.html + or view the online version at + http://www.boost.org/regression-logs/cs-win32_metacomm/doc/html/boost_typetraits.html + + + +