From d83ea9e52e174aebff49c4291096a5157b8ca6a7 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 27 Jul 2000 13:38:51 +0000 Subject: [PATCH] Initial HTML commit [SVN r7634] --- call_traits.htm | 738 ++++++++++++++++++++++++++++++++++++++++++++ cast.htm | 148 +++++++++ compressed_pair.htm | 92 ++++++ index.htm | 72 +++++ operators.htm | 598 +++++++++++++++++++++++++++++++++++ type_traits.htm | 588 +++++++++++++++++++++++++++++++++++ utility.htm | 103 +++++++ 7 files changed, 2339 insertions(+) create mode 100644 call_traits.htm create mode 100644 cast.htm create mode 100644 compressed_pair.htm create mode 100644 index.htm create mode 100644 operators.htm create mode 100644 type_traits.htm create mode 100644 utility.htm diff --git a/call_traits.htm b/call_traits.htm new file mode 100644 index 0000000..d0a0fde --- /dev/null +++ b/call_traits.htm @@ -0,0 +1,738 @@ + + + + + + +Call Traits + + + + +

Header +<boost/call_traits.hpp>

+ +

All of the contents of <boost/call_traits.hpp> are +defined inside namespace boost.

+ +

The template class call_traits<T> encapsulates the +"best" method to pass a parameter of some type T to or +from a function, and consists of a collection of typedefs defined +as in the table below. The purpose of call_traits is to ensure +that problems like "references to references" +never occur, and that parameters are passed in the most efficient +manner possible (see examples). In each +case if your existing practice is to use the type defined on the +left, then replace it with the call_traits defined type on the +right. Note that for compilers that do not support partial +specialization, no benefit will occur from using call_traits: the +call_traits defined types will always be the same as the existing +practice in this case.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Existing practice

+

call_traits equivalent

+

Description

+

Notes

+

T
+ (return by value)

+

call_traits<T>::value_type

+
Defines a type that + represents the "value" of type T. Use this for + functions that return by value, or possibly for stored + values of type T.

2

+

T&
+ (return value)

+

call_traits<T>::reference

+
Defines a type that + represents a reference to type T. Use for functions that + would normally return a T&.

1

+

const T&
+ (return value)

+

call_traits<T>::const_reference

+
Defines a type that + represents a constant reference to type T. Use for + functions that would normally return a const T&.

1

+

const T&
+ (function parameter)

+

call_traits<T>::param_type

+
Defines a type that + represents the "best" way to pass a parameter + of type T to a function.

1,3

+
+ +

Notes:

+ +
    +
  1. If T is already reference type, then call_traits is + defined such that references to + references do not occur (requires partial + specialization).
  2. +
  3. If T is an array type, then call_traits defines value_type + as a "constant pointer to type" rather than an + "array of type" (requires partial + specialization). Note that if you are using value_type as + a stored value then this will result in storing a "constant + pointer to an array" rather than the array itself. + This may or may not be a good thing depending upon what + you actually need (in other words take care!).
  4. +
  5. If T is a small built in type or a pointer, then param_type + is defined as T const, instead of T + const&. This can improve the ability of the + compiler to optimize loops in the body of the function if + they depend upon the passed parameter, the semantics of + the passed parameter is otherwise unchanged (requires + partial specialization).
  6. +
+ +

 

+ +

Copy constructibility

+ +

The following table defines which call_traits types can always +be copy-constructed from which other types, those entries marked +with a '?' are true only if and only if T is copy constructible:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 

To:

+
From:

T

+

value_type

+

reference

+

const_reference

+

param_type

+
T

?

+

?

+

Y

+

Y

+

Y

+
value_type

?

+

?

+

N

+

N

+

Y

+
reference

?

+

?

+

Y

+

Y

+

Y

+
const_reference

?

+

N

+

N

+

Y

+

Y

+
param_type

?

+

?

+

N

+

N

+

Y

+
+ +

 

+ +

If T is an assignable type the following assignments are +possible:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 

To:

+
From:

T

+

value_type

+

reference

+

const_reference

+

param_type

+
T

Y

+

Y

+

-

+

-

+

-

+
value_type

Y

+

Y

+

-

+

-

+

-

+
reference

Y

+

Y

+

-

+

-

+

-

+
const_reference

Y

+

Y

+

-

+

-

+

-

+
param_type

Y

+

Y

+

-

+

-

+

-

+
+ +

 

+ +

Examples

+ +

The following table shows the effect that call_traits has on +various types, the table assumes that the compiler supports +partial specialization: if it doesn't then all types behave in +the same way as the entry for "myclass", and call_traits +can not be used with reference or array types.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 

Call_traits type:

+

Original type T

+

value_type

+

reference

+

const_reference

+

param_type

+

Applies to:

+

myclass

+

myclass

+

myclass&

+

const + myclass&

+

myclass + const&

+

All user + defined types.

+

int

+

int

+

int&

+

const int&

+

int const

+

All small + built-in types.

+

int*

+

int*

+

int*&

+

int*const&

+

int* const

+

All + pointer types.

+

int&

+

int&

+

int&

+

const int&

+

int&

+

All + reference types.

+

const int&

+

const int&

+

const int&

+

const int&

+

const int&

+

All + constant-references.

+

int[3]

+

const int*

+

int(&)[3]

+

const int(&)[3]

+

const int* + const

+

All array + types.

+

const int[3]

+

const int*

+

const int(&)[3]

+

const int(&)[3]

+

const int* + const

+

All + constant-array types.

+
+ +

 

+ +

Example 1:

+ +

The following class is a trivial class that stores some type T +by value (see the call_traits_test.cpp +file), the aim is to illustrate how each of the available call_traits +typedefs may be used:

+ +
template <class T>
+struct contained
+{
+   // define our typedefs first, arrays are stored by value
+   // so value_type is not the same as result_type:
+   typedef typename boost::call_traits<T>::param_type       param_type;
+   typedef typename boost::call_traits<T>::reference        reference;
+   typedef typename boost::call_traits<T>::const_reference  const_reference;
+   typedef T                                                value_type;
+   typedef typename boost::call_traits<T>::value_type       result_type;
+
+   // stored value:
+   value_type v_;
+   
+   // constructors:
+   contained() {}
+   contained(param_type p) : v_(p){}
+   // return byval:
+   result_type value() { return v_; }
+   // return by_ref:
+   reference get() { return v_; }
+   const_reference const_get()const { return v_; }
+   // pass value:
+   void call(param_type p){}
+
+};
+ +

Example 2 (the reference to reference +problem):

+ +

Consider the definition of std::binder1st:

+ +
template <class Operation> 
+class binder1st : 
+   public unary_function<Operation::second_argument_type, Operation::result_type> 
+{ 
+protected: 
+   Operation op; 
+   Operation::first_argument_type value; 
+public: 
+   binder1st(const Operation& x, const Operation::first_argument_type& y); 
+   Operation::result_type operator()(const Operation::second_argument_type& x) const; 
+}; 
+ +

Now consider what happens in the relatively common case that +the functor takes its second argument as a reference, that +implies that Operation::second_argument_type is a +reference type, operator() will now end up taking a +reference to a reference as an argument, and that is not +currently legal. The solution here is to modify operator() +to use call_traits:

+ +
Operation::result_type operator()(call_traits<Operation::second_argument_type>::param_type x) const;
+ +

Now in the case that Operation::second_argument_type +is a reference type, the argument is passed as a reference, and +the no "reference to reference" occurs.

+ +

Example 3 (the make_pair problem):

+ +

If we pass the name of an array as one (or both) arguments to std::make_pair, +then template argument deduction deduces the passed parameter as +"const reference to array of T", this also applies to +string literals (which are really array literals). Consequently +instead of returning a pair of pointers, it tries to return a +pair of arrays, and since an array type is not copy-constructible +the code fails to compile. One solution is to explicitly cast the +arguments to make_pair to pointers, but call_traits provides a +better (i.e. automatic) solution (and one that works safely even +in generic code where the cast might do the wrong thing):

+ +
template <class T1, class T2>
+std::pair<
+   typename boost::call_traits<T1>::value_type, 
+   typename boost::call_traits<T2>::value_type> 
+      make_pair(const T1& t1, const T2& t2)
+{
+   return std::pair<
+      typename boost::call_traits<T1>::value_type, 
+      typename boost::call_traits<T2>::value_type>(t1, t2);
+}
+ +

Here, the deduced argument types will be automatically +degraded to pointers if the deduced types are arrays, similar +situations occur in the standard binders and adapters: in +principle in any function that "wraps" a temporary +whose type is deduced.

+ +

Example 4 (optimising fill):

+ +

The call_traits template will "optimize" the passing +of a small built-in type as a function parameter, this mainly has +an effect when the parameter is used within a loop body. In the +following example (see algo_opt_examples.cpp), +a version of std::fill is optimized in two ways: if the type +passed is a single byte built-in type then std::memset is used to +effect the fill, otherwise a conventional C++ implemention is +used, but with the passed parameter "optimized" using +call_traits:

+ +
namespace detail{
+
+template <bool opt>
+struct filler
+{
+   template <typename I, typename T>
+   static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val);
+   {
+      while(first != last)
+      {
+         *first = val;
+         ++first;
+      }
+   }
+};
+
+template <>
+struct filler<true>
+{
+   template <typename I, typename T>
+   static void do_fill(I first, I last, T val)
+   {
+      memset(first, val, last-first);
+   }
+};
+
+}
+
+template <class I, class T>
+inline void fill(I first, I last, const T& val)
+{
+   enum{ can_opt = boost::is_pointer<I>::value
+                   && boost::is_arithmetic<T>::value
+                   && (sizeof(T) == 1) };
+   typedef detail::filler<can_opt> filler_t;
+   filler_t::template do_fill<I,T>(first, last, val);
+}
+ +

Footnote: the reason that this is "optimal" for +small built-in types is that with the value passed as "T +const" instead of "const T&" the compiler is +able to tell both that the value is constant and that it is free +of aliases. With this information the compiler is able to cache +the passed value in a register, unroll the loop, or use +explicitly parallel instructions: if any of these are supported. +Exactly how much mileage you will get from this depends upon your +compiler - we could really use some accurate benchmarking +software as part of boost for cases like this.

+ +

Rationale

+ +

The following notes are intended to briefly describe the +rational behind choices made in call_traits.

+ +

All user-defined types follow "existing practice" +and need no comment.

+ +

Small built-in types (what the standard calls fundamental +types [3.9.1]) differ from existing practice only in the param_type +typedef. In this case passing "T const" is compatible +with existing practice, but may improve performance in some cases +(see Example 4), in any case this should never +be any worse than existing practice.

+ +

Pointers follow the same rational as small built-in types.

+ +

For reference types the rational follows Example +2 - references to references are not allowed, so the call_traits +members must be defined such that these problems do not occur. +There is a proposal to modify the language such that "a +reference to a reference is a reference" (issue #106, +submitted by Bjarne Stroustrup), call_traits<T>::value_type +and call_traits<T>::param_type both provide the same effect +as that proposal, without the need for a language change (in +other words it's a workaround).

+ +

For array types, a function that takes an array as an argument +will degrade the array type to a pointer type: this means that +the type of the actual parameter is different from its declared +type, something that can cause endless problems in template code +that relies on the declared type of a parameter. For example:

+ +
template <class T>
+struct A
+{
+   void foo(T t);
+};
+ +

In this case if we instantiate A<int[2]> +then the declared type of the parameter passed to member function +foo is int[2], but it's actual type is const int*, if we try to +use the type T within the function body, then there is a strong +likelyhood that our code will not compile:

+ +
template <class T>
+void A<T>::foo(T t)
+{
+   T dup(t); // doesn't compile for case that T is an array.
+}
+ +

By using call_traits the degradation from array to pointer is +explicit, and the type of the parameter is the same as it's +declared type:

+ +
template <class T>
+struct A
+{
+   void foo(call_traits<T>::value_type t);
+};
+
+template <class T>
+void A<T>::foo(call_traits<T>::value_type t)
+{
+   call_traits<T>::value_type dup(t); // OK even if T is an array type.
+}
+ +

For value_type (return by value), again only a pointer may be +returned, not a copy of the whole array, and again call_traits +makes the degradation explicit. The value_type member is useful +whenever an array must be explicitly degraded to a pointer - Example 3 provides the test case (Footnote: the +array specialisation for call_traits is the least well understood +of all the call_traits specialisations, if the given semantics +cause specific problems for you, or don't solve a particular +array-related problem, then I would be interested to hear about +it. Most people though will probably never need to use this +specialisation).

+ +
+ +

Revised 18 June 2000

+ +

© Copyright boost.org 2000. 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.

+ +

Based on contributions by Steve Cleary, Beman Dawes, Howard +Hinnant and John Maddock.

+ +

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

+ +

.

+ +

 

+ +

 

+ + diff --git a/cast.htm b/cast.htm new file mode 100644 index 0000000..2ebb685 --- /dev/null +++ b/cast.htm @@ -0,0 +1,148 @@ + + + + + + +Header boost/cast.hpp Documentation + + + + +

c++boost.gif (8819 bytes)Header +boost/cast.hpp

+

Cast Functions

+

The header boost/cast.hpp +provides polymorphic_cast, polymorphic_downcast, +and numeric_cast template functions designed +to complement the C++ Standard's built-in casts.

+

The program cast_test.cpp can be used to +verify these function templates work as expected.

+

polymorphic_cast was suggested by Bjarne Stroustrup in "The C++ +Programming Language".
+polymorphic_downcast was contributed by Dave +Abrahams.
+numeric_cast
was contributed by Kevlin +Henney.

+

Namespace synopsis

+
+
namespace boost {
+    namespace cast {
+        // all synopsis below included here
+    }
+  using ::boost::cast::polymorphic_cast;
+  using ::boost::cast::polymorphic_downcast;
+  using ::boost::cast::bad_numeric_cast;
+  using ::boost::cast::numeric_cast;
+}
+
+

Polymorphic casts

+

Pointers to polymorphic objects (objects of classes which define at least one +virtual function) are sometimes downcast or crosscast.  Downcasting means +casting from a base class to a derived class.  Crosscasting means casting +across an inheritance hierarchy diagram, such as from one base to the other in a +Y diagram hierarchy.

+

Such casts can be done with old-style casts, but this approach is never to be +recommended.  Old-style casts are sorely lacking in type safety, suffer +poor readability, and are difficult to locate with search tools.

+

The C++ built-in static_cast can be used for efficiently downcasting +pointers to polymorphic objects, but provides no error detection for the case +where the pointer being cast actually points to the wrong derived class. The polymorphic_downcast +template retains the efficiency of static_cast for non-debug +compilations, but for debug compilations adds safety via an assert() that a dynamic_cast +succeeds.  

+

The C++ built-in dynamic_cast can be used for downcasts and crosscasts +of pointers to polymorphic objects, but error notification in the form of a +returned value of 0 is inconvenient to test, or worse yet, easy to forget to +test.  The polymorphic_cast template performs a dynamic_cast, +and throws an exception if the dynamic_cast returns 0.

+

A polymorphic_downcast is preferred when debug-mode tests will cover +100% of the object types possibly cast and when non-debug-mode efficiency is an +issue. If these two conditions are not present, polymorphic_cast is +preferred.  It must also be used for crosscasts.  It does an assert( +dynamic_cast<Derived>(x) == x ) where x is the base pointer, ensuring that +not only is a non-zero pointer returned, but also that it correct in the +presence of multiple inheritance. . Warning:: Because polymorphic_downcast +uses assert(), it violates the One Definition Rule if NDEBUG is inconsistently +defined across translation units.

+

The C++ built-in dynamic_cast must be used to cast references rather +than pointers.  It is also the only cast that can be used to check whether +a given interface is supported; in that case a return of 0 isn't an error +condition.

+

polymorphic_cast and polymorphic_downcast synopsis

+
+
template <class Derived, class Base>
+inline Derived polymorphic_cast(Base* x);
+// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
+// Returns: dynamic_cast<Derived>(x)
+
+template <class Derived, class Base>
+inline Derived polymorphic_downcast(Base* x);
+// Effects: assert( dynamic_cast<Derived>(x) == x );
+// Returns: static_cast<Derived>(x)
+
+

polymorphic_downcast example

+
+
#include <boost/cast.hpp>
+...
+class Fruit { public: virtual ~Fruit(){}; ... };
+class Banana : public Fruit { ... };
+...
+void f( Fruit * fruit ) {
+// ... logic which leads us to believe it is a Banana
+  Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
+  ...
+
+

numeric_cast

+

A static_cast, implicit_cast or implicit conversion will not +detect failure to preserve range for numeric casts. The numeric_cast +template function are similar to static_cast and certain (dubious) +implicit conversions in this respect, except that they detect loss of numeric +range. An exception is thrown when a runtime value preservation check fails.

+

The requirements on the argument and result types are:

+
+ +
+

numeric_cast synopsis

+
+
class bad_numeric_cast : public std::bad_cast {...};
+
+template<typename Target, typename Source>
+  inline Target numeric_cast(Source arg);
+    // Throws:  bad_numeric_cast unless, in converting arg from Source to Target,
+    //          there is no loss of negative range, and no underflow, and no
+    //          overflow, as determined by std::numeric_limits
+    // Returns: static_cast<Target>(arg)
+
+

numeric_cast example

+
+
#include <boost/cast.hpp>
+using namespace boost::cast;
+
+void ariane(double vx)
+{
+    ...
+    unsigned short dx = numeric_cast<unsigned short>(vx);
+    ...
+}
+
+

numeric_cast rationale

+

The form of the throws condition is specified so that != is not a required +operation.

+
+

Revised  28 June, 2000

+

© Copyright boost.org 1999. 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.

+ + + + diff --git a/compressed_pair.htm b/compressed_pair.htm new file mode 100644 index 0000000..d63af7f --- /dev/null +++ b/compressed_pair.htm @@ -0,0 +1,92 @@ + + + + + + +Header <boost/compressed_pair.hpp> + + + + +

Header +<boost/compressed_pair.hpp>

+ +

All of the contents of <boost/compressed_pair.hpp> are +defined inside namespace boost.

+ +

The class compressed pair is very similar to std::pair, but if +either of the template arguments are empty classes, then the +"empty member optimisation" is applied to compress the +size of the pair.

+ +
template <class T1, class T2>
+class compressed_pair
+{
+public:
+	typedef T1                                                 first_type;
+	typedef T2                                                 second_type;
+	typedef typename call_traits<first_type>::param_type       first_param_type;
+	typedef typename call_traits<second_type>::param_type      second_param_type;
+	typedef typename call_traits<first_type>::reference        first_reference;
+	typedef typename call_traits<second_type>::reference       second_reference;
+	typedef typename call_traits<first_type>::const_reference  first_const_reference;
+	typedef typename call_traits<second_type>::const_reference second_const_reference;
+
+	         compressed_pair() : base() {}
+	         compressed_pair(first_param_type x, second_param_type y);
+	explicit compressed_pair(first_param_type x);
+	explicit compressed_pair(second_param_type y);
+
+	first_reference       first();
+	first_const_reference first() const;
+
+	second_reference       second();
+	second_const_reference second() const;
+
+	void swap(compressed_pair& y);
+};
+ +

The two members of the pair can be accessed using the member +functions first() and second(). Note that not all member +functions can be instantiated for all template parameter types. +In particular compressed_pair can be instantiated for reference +and array types, however in these cases the range of constructors +that can be used are limited. If types T1 and T2 are the same +type, then there is only one version of the single-argument +constructor, and this constructor initialises both values in the +pair to the passed value.

+ +

Note that compressed_pair can not be instantiated if either of +the template arguments is an enumerator type, unless there is +compiler support for boost::is_enum, or if boost::is_enum is +specialised for the enumerator type.

+ +

Finally, compressed_pair requires compiler support for partial +specialisation of class templates - without that support +compressed_pair behaves just like std::pair.

+ +
+ +

Revised 08 March 2000

+ +

© Copyright boost.org 2000. 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.

+ +

Based on contributions by Steve Cleary, Beman Dawes, Howard +Hinnant and John Maddock.

+ +

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

+ +

 

+ + diff --git a/index.htm b/index.htm new file mode 100644 index 0000000..543abb1 --- /dev/null +++ b/index.htm @@ -0,0 +1,72 @@ + + + + + + +Boost Utility Library + + + + + + + + + + + + + +
c++boost.gif (8819 bytes)HomeLibrariesPeopleFAQMore
+

Boost Utility Library

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HeaderContents
boost/utility.hpp
+
[Documentation]
Class noncopyable plus next() and prior() template + functions.
boost/cast.hpp
+ [Documentation]
polymorphic_cast, implicit_cast, and numeric_cast + function templates. +

[Beta.]

+
boost/operators.hpp
+ [Documentation]
Templates equality_comparable, less_than_comparable, addable, + and the like ease the task of defining comparison and arithmetic + operators, and iterators.
boost/type_traits.hpp
+ [Documentation]
+ [DDJ Article "C++ type traits"]
Template classes that describe the fundamental properties of a type.
boost/call_traits.hpp
+ [Documentation]
Template class call_traits<T>, that defines types used for passing + parameters to and from a proceedure.
boost/compressed_pair.hpp
+ [Documentation]
Template class compressed_pait<T1, T2> which pairs two values + using the empty member optimisation where appropriate.
+

Revised 24 July 2000

+ + + + diff --git a/operators.htm b/operators.htm new file mode 100644 index 0000000..ea57f14 --- /dev/null +++ b/operators.htm @@ -0,0 +1,598 @@ + + + + + + +Header boost/operators.hpp Documentation + + + + +

c++boost.gif (8819 bytes)Header +boost/operators.hpp

+

Header boost/operators.hpp +supplies (in namespace boost) several sets of templates:

+ +

These templates define many global operators in terms of a minimal number of +fundamental operators.

+

Arithmetic Operators

+

If, for example, you declare a class like this:

+
+
class MyInt : boost::operators<MyInt>
+{
+    bool operator<(const MyInt& x) const; 
+    bool operator==(const MyInt& x) const;
+    MyInt& operator+=(const MyInt& x);    
+    MyInt& operator-=(const MyInt& x);    
+    MyInt& operator*=(const MyInt& x);    
+    MyInt& operator/=(const MyInt& x);    
+    MyInt& operator%=(const MyInt& x);    
+    MyInt& operator|=(const MyInt& x);    
+    MyInt& operator&=(const MyInt& x);    
+    MyInt& operator^=(const MyInt& x);    
+    MyInt& operator++();    
+    MyInt& operator--();    
+};
+
+

then the operators<> template adds more than a dozen +additional operators, such as operator>, <=, >=, and +.  Two-argument +forms of the templates are also provided to allow interaction with other +types.

+

Dave Abrahams +started the library and contributed the arithmetic operators in boost/operators.hpp.
+Jeremy Siek +contributed the dereference operators and iterator +helpers in boost/operators.hpp.
+Aleksey Gurtovoy +contributed the code to support base class chaining +while remaining backward-compatible with old versions of the library.
+Beman Dawes +contributed test_operators.cpp.

+

Rationale

+

Overloaded operators for class types typically occur in groups. If you can +write x + y, you probably also want to be able to write x += +y. If you can write x < y, you also want x > y, +x >= y, and x <= y. Moreover, unless your class has +really surprising behavior, some of these related operators can be defined in +terms of others (e.g. x >= y <=> !(x < y)). +Replicating this boilerplate for multiple classes is both tedious and +error-prone. The boost/operators.hpp +templates help by generating operators for you at namespace scope based on other +operators you've defined in your class.

+ +

Two-Argument Template Forms

+
+

The arguments to a binary operator commonly have identical types, but it is +not unusual to want to define operators which combine different types. For example, +one might want to multiply a mathematical vector by a scalar. The two-argument +template forms of the arithmetic operator templates are supplied for this +purpose. When applying the two-argument form of a template, the desired return +type of the operators typically determines which of the two types in question +should be derived from the operator template. For example, if the result of T + U +is of type T, then T (not U) should be +derived from addable<T,U>. The comparison templates less_than_comparable<> +and equality_comparable<> +are exceptions to this guideline, since the return type of the operators they +define is bool.

+

On compilers which do not support partial specialization, the two-argument +forms must be specified by using the names shown below with the trailing '2'. +The single-argument forms with the trailing '1' are provided for +symmetry and to enable certain applications of the base +class chaining technique.

+

Arithmetic operators table

+

The requirements for the types used to instantiate operator templates are +specified in terms of expressions which must be valid and by the return type of +the expression. In the following table t and t1 are +values of type T, and u is a value of type U. +Every template in the library other than operators<> +and operators2<> has an additional +optional template parameter B which is not shown in the table, but +is explained below

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
templatetemplate will supplyRequirements
operators<T>All the other <T> templates in this table.All the <T> requirements in this table.
operators<T,U>
+ operators2<T,U>
All the other <T,U> templates in this table, plus incrementable<T> + and decrementable<T>.All the <T,U> requirements in this table*, + plus incrementable<T> and decrementable<T>.
less_than_comparable<T>
+ less_than_comparable1<T>
bool operator>(const T&, const T&) 
+ bool operator<=(const T&, const T&)
+ bool operator>=(const T&, const T&)
t<t1. Return convertible to bool
less_than_comparable<T,U>
+ less_than_comparable2<T,U>
bool operator<=(const T&, const U&)
+ bool operator>=(const T&, const U&)
+ bool operator>(const U&, const T&) 
+ bool operator<(const U&, const T&) 
+ bool operator<=(const U&, const T&)
+ bool operator>=(const U&, const T&)
t<u. Return convertible to bool
+ t>u. Return convertible to bool
equality_comparable<T>
+ equality_comparable1<T>
bool operator!=(const T&, const T&)t==t1. Return convertible to bool
equality_comparable<T,U>
+ equality_comparable2<T,U>
friend bool operator==(const U&, const T&)
+ friend bool operator!=(const U&, const T&)
+ friend bool operator!=( const T&, const U&)
t==u. Return convertible to bool
addable<T>
+ addable1<T>
T operator+(T, const T&)t+=t1. Return convertible to T
addable<T,U>
+ addable2<T,U>
T operator+(T, const U&)
+ T operator+(const U&, T )
t+=u. Return convertible to T
subtractable<T>
+ subtractable1<T>
T operator-(T, const T&)t-=t1. Return convertible to T
subtractable<T,U>
+ subtractable2<T,U>
T operator-(T, const U&)t-=u. Return convertible to T
multipliable<T>
+ multipliable1<T>
T operator*(T, const T&)t*=t1. Return convertible to T
multipliable<T,U>
+ multipliable2<T,U>
T operator*(T, const U&)
+ T operator*(const U&, T )
t*=u. Return convertible to T
dividable<T>
+ dividable1<T>
T operator/(T, const T&)t/=t1. Return convertible to T
dividable<T,U>
+ dividable2<T,U>
T operator/(T, const U&)t/=u. Return convertible to T
modable<T>
+ modable1<T>
T operator%(T, const T&)t%=t1. Return convertible to T
modable<T,U>
+ modable2<T,U>
T operator%(T, const U&)t%=u. Return convertible to T
orable<T>
+ orable1<T>
T operator|(T, const T&)t|=t1. Return convertible to T
orable<T,U>
+ orable2<T,U>
T operator|(T, const U&)
+ T operator|(const U&, T )
t|=u. Return convertible to T
andable<T>
+ andable1<T>
T operator&(T, const T&)t&=t1. Return convertible to T
andable<T,U>
+ andable2<T,U>
T operator&(T, const U&)
+ T operator&(const U&, T)
t&=u. Return convertible to T
xorable<T>
+ xorable1<T>
T operator^(T, const T&)t^=t1. Return convertible to T
xorable<T,U>
+ xorable2<T,U>
T operator^(T, const U&)
+ T operator^(const U&, T )
t^=u. Return convertible to T
incrementable<T>
+ incrementable1<T>
T operator++(T& x, int)T temp(x); ++x; return temp;
+ Return convertible to T
decrementable<T>
+ decrementable1<T>
T operator--(T& x, int)T temp(x); --x; return temp;
+ Return convertible to T
+
+Portability Note: many compilers (e.g. MSVC6.3, +GCC 2.95.2) will not enforce the requirements in this table unless the +operations which depend on them are actually used. This is not +standard-conforming behavior. If you are trying to write portable code it is +important not to rely on this bug. In particular, it would be convenient to +derive all your classes which need binary operators from the operators<> +and operators2<> templates, +regardless of whether they implement all the requirements in the table. Even if +this works with your compiler today, it may not work tomorrow. +

Base Class Chaining and Object Size

+

Every template listed in the table except operators<> +and operators2<> has an additional +optional template parameter B.  If supplied, B +must be a class type; the resulting class will be publicly derived from B. This +can be used to avoid the object size bloat commonly associated with multiple +empty base classes (see the note for users of older +versions below for more details). To provide support for several groups of +operators, use the additional parameter to chain operator templates into a +single-base class hierarchy, as in the following example.

+

Caveat: to chain to a base class which is not a boost operator +template when using the single-argument form of a +boost operator template, you must specify the operator template with the +trailing '1' in its name. Otherwise the library will assume you +mean to define a binary operation combining the class you intend to use as a +base class and the class you're deriving.

+

Borland users: even single-inheritance seems to cause an increase in +object size in some cases. If you are not defining a template, you may get +better object-size performance by avoiding derivation altogether, and instead +explicitly instantiating the operator template as follows: +

+    class myclass // lose the inheritance...
+    {
+        //...
+    };
+    // explicitly instantiate the operators I need.
+    template class less_than_comparable<myclass>;
+    template class equality_comparable<myclass>;
+    template class incrementable<myclass>;
+    template class decrementable<myclass>;
+    template class addable<myclass,long>;
+    template class subtractable<myclass,long>;
+
+
+

Usage example

+
+
template <class T>
+class point    // note: private inheritance is OK here!
+    : boost::addable< point<T>          // point + point
+    , boost::subtractable< point<T>     // point - point
+    , boost::dividable2< point<T>, T    // point / T
+    , boost::multipliable2< point<T>, T // point * T, T * point
+      > > > >
+{
+public:
+    point(T, T);
+    T x() const;
+    T y() const;
+
+    point operator+=(const point&);
+    // point operator+(point, const point&) automatically
+    // generated by addable.
+
+    point operator-=(const point&);
+    // point operator-(point, const point&) automatically
+    // generated by subtractable.
+
+    point operator*=(T);
+    // point operator*(point, const T&) and
+    // point operator*(const T&, point) auto-generated
+    // by multipliable.
+
+    point operator/=(T);
+    // point operator/(point, const T&) auto-generated
+    // by dividable.
+private:
+    T x_;
+    T y_;
+};
+
+// now use the point<> class:
+
+template <class T>
+T length(const point<T> p)
+{
+    return sqrt(p.x()*p.x() + p.y()*p.y());
+}
+
+const point<float> right(0, 1);
+const point<float> up(1, 0);
+const point<float> pi_over_4 = up + right;
+const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4);
+

Arithmetic operators demonstration and test program

+

The operators_test.cpp +program demonstrates the use of the arithmetic operator templates, and can also +be used to verify correct operation.

+

The test program has been compiled and run successfully with: 

+ +

Dereference operators and iterator helpers

+

The iterator helper templates ease the task +of creating a custom iterator. Similar to arithmetic types, a complete iterator +has many operators that are "redundant" and can be implemented in +terms of the core set of operators.

+

The dereference operators were motivated by the iterator +helpers, but are often useful in non-iterator contexts as well. Many of the +redundant iterator operators are also arithmetic operators, so the iterator +helper classes borrow many of the operators defined above. In fact, only two new +operators need to be defined! (the pointer-to-member operator-> +and the subscript operator[]). +

Notation

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tis the user-defined type for which the operations are + being supplied.
Vis the type which the resulting dereferenceable + type "points to", or the value_type of the custom + iterator.
Dis the type used to index the resulting indexable + type or the difference_type of the custom iterator.
Pis a type which can be dereferenced to access V, + or the pointer type of the custom iterator.
Ris the type returned by indexing the indexable + type or the reference type of the custom iterator.
iis short for static_cast<const T&>(*this), + where this is a pointer to the helper class.
+ Another words, i should be an object of the custom iterator + type.
x,x1,x2are objects of type T.
nis an object of type D.
+

The requirements for the types used to instantiate the dereference operators +and iterator helpers are specified in terms of expressions which must be valid +and their return type. 

+

Dereference operators

+

The dereference operator templates in this table all accept an optional +template parameter (not shown) to be used for base class +chaining. + + + + + + + + + + + + + + + + + + +
templatetemplate will supplyRequirements
dereferenceable<T,P>P operator->() const(&*i.). Return convertible to P.
indexable<T,D,R>R operator[](D n) const*(i + n). Return of type R.
+

Iterator helpers

+

There are three separate iterator helper classes, each for a different +category of iterator. Here is a summary of the core set of operators that the +custom iterator must define, and the extra operators that are created by the +helper classes. For convenience, the helper classes also fill in all of the +typedef's required of iterators by the C++ standard (iterator_category, +value_type, etc.).

+ + + + + + + + + + + + + + + + + + + + + + + +
templatetemplate will supplyRequirements
forward_iterator_helper
+ <T,V,D,P,R>
bool operator!=(const T& x1, const T& x2)
+ T operator++(T& x, int)
+ V* operator->() const
+
x1==x2. Return convertible to bool
+ T temp(x); ++x; return temp;
+ (&*i.). Return convertible to V*.
bidirectional_iterator_helper
+ <T,V,D,P,R>
Same as above, plus
+ T operator--(T& x, int)
Same as above, plus
+ T temp(x); --x; return temp;
random_access_iterator_helper
+ <T,V,D,P,R>
Same as above, plus
+ T operator+(T x, const D&)
+ T operator+(const D& n, T x)
+ T operator-(T x, const D& n)
+ R operator[](D n) const
+ bool operator>(const T& x1, const T& x2) 
+ bool operator<=(const T& x1, const T& x2)
+ bool operator>=(const T& x1, const T& x2)
Same as above, plus
+ x+=n. Return convertible to T
+ x-=n. Return convertible to T
+ x1<x2. Return convertible to bool
+ And to satisfy RandomAccessIterator:
+ x1-x2. Return convertible to D
+

Iterator demonstration and test program

+

The iterators_test.cpp +program demonstrates the use of the iterator templates, and can also be used to +verify correct operation. The following is the custom iterator defined in the +test program. It demonstrates a correct (though trivial) implementation of the +core operations that must be defined in order for the iterator helpers to +"fill in" the rest of the iterator operations.

+
+
template <class T, class R, class P>
+struct test_iter
+  : public boost::random_access_iterator_helper<
+     test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
+{
+  typedef test_iter self;
+  typedef R Reference;
+  typedef std::ptrdiff_t Distance;
+
+public:
+  test_iter(T* i) : _i(i) { }
+  test_iter(const self& x) : _i(x._i) { }
+  self& operator=(const self& x) { _i = x._i; return *this; }
+  Reference operator*() const { return *_i; }
+  self& operator++() { ++_i; return *this; }
+  self& operator--() { --_i; return *this; }
+  self& operator+=(Distance n) { _i += n; return *this; }
+  self& operator-=(Distance n) { _i -= n; return *this; }
+  bool operator==(const self& x) const { return _i == x._i; }
+  bool operator<(const self& x) const { return _i < x._i; }
+  friend Distance operator-(const self& x, const self& y) {
+    return x._i - y._i; 
+  }
+protected:
+  T* _i;
+};
+
+

It has been compiled and run successfully with:

+ +

Jeremy Siek +contributed the iterator operators and helpers.  He also contributed iterators_test.cpp

+
+

Note for users of older versions

+

The changes in the library interface and recommended +usage were motivated by some practical issues described below. The new +version of the library is still backward-compatible with the former one (so +you're not forced change any existing code), but the old usage is +deprecated. Though it was arguably simpler and more intuitive than using base +class chaining, it has been discovered that the old practice of deriving +from multiple operator templates can cause the resulting classes to be much +larger than they should be. Most modern C++ compilers significantly bloat the +size of classes derived from multiple empty base classes, even though the base +classes themselves have no state. For instance, the size of point<int> +from the example above was 12-24 bytes on various compilers +for the Win32 platform, instead of the expected 8 bytes. +

Strictly speaking, it was not the library's fault - the language rules allow +the compiler to apply the empty base class optimization in that situation. In +principle an arbitrary number of empty base classes can be allocated at the same +offset, provided that none of them have a common ancestor (see section 10.5 [class.derived], +par. 5 of the standard). But the language definition also doesn't require +implementations to do the optimization, and few if any of today's compilers +implement it when multiple inheritance is involved. What's worse, it is very +unlikely that implementors will adopt it as a future enhancement to existing +compilers, because it would break binary compatibility between code generated by +two different versions of the same compiler. As Matt Austern said, "One of +the few times when you have the freedom to do this sort of thing is when you're +targeting a new architecture...". On the other hand, many common compilers +will use the empty base optimization for single inheritance hierarchies.

+

Given the importance of the issue for the users of the library (which aims to +be useful for writing light-weight classes like MyInt or point<>), +and the forces described above, we decided to change the library interface so +that the object size bloat could be eliminated even on compilers that support +only the simplest form of the empty base class optimization. The current library +interface is the result of those changes. Though the new usage is a bit more +complicated than the old one, we think it's worth it to make the library more +useful in real world. Alexy Gurtovoy contributed the code which supports the new +usage idiom while allowing the library remain backward-compatible.

+
+

Revised 28 Jun 2000 +

+

© Copyright David Abrahams and Beman Dawes 1999-2000. 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.

+ + + + diff --git a/type_traits.htm b/type_traits.htm new file mode 100644 index 0000000..dae21d7 --- /dev/null +++ b/type_traits.htm @@ -0,0 +1,588 @@ + + + + + + +Type Traits + + + + +

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. This documentation is +divided up into the following sections:

+ +
Fundamental type operations
+Fundamental type properties
+   cv-Qualifiers
+   Fundamental Types
+   Compound Types
+   Object/Scalar Types
+Compiler Support Information
+Example Code
+ +

Fundamental type operations

+ +

Usage: "class_name<T>::type" performs +indicated transformation on type T.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Expression.

+

Description.

+

Compiler.

+
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".

P

+
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".

P

+
remove_cv<T>::typeCreates a type the same as T + but with any top level cv-qualifiers removed. For example + "const int" would become "int", and + "volatile double" would become "double".

P

+
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.

P

+
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&".

P

+
remove_bounds<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]".

P

+
+ +

 

+ +

Fundamental type properties

+ +

Usage: "class_name<T>::value" is true if +indicated property is true, false otherwise. (Note that class_name<T>::value +is always defined as a compile time constant).

+ +

cv-Qualifiers

+ +

The following classes determine what cv-qualifiers are present +on a type (see 3.93).

+ + + + + + + + + + + + + + + + + + + + + + +

Expression.

+

Description.

+

Compiler.

+
is_const<T>::valueTrue if type T is top-level + const qualified.

P

+
is_volatile<T>::valueTrue if type T is top-level + volatile qualified.

P

+
is_same<T,U>::valueTrue if T and U are the same + type.

P

+
+ +

 

+ +

Fundamental Types

+ +

The following will only ever be true for cv-unqualified types; +these are closely based on the section 3.9 of the C++ Standard.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Expression.

+

Description.

+

Compiler.

+
is_void<T>::valueTrue only if T is void. 
is_standard_unsigned_integral<T>::valueTrue only if T is one of the + standard unsigned integral types (3.9.1 p3) - unsigned + char, unsigned short, unsigned int, and unsigned long. 
is_standard_signed_integral<T>::valueTrue only if T is one of the + standard signed integral types (3.9.1 p2) - signed char, + short, int, and long. 
is_standard_integral<T>::valueTrue if T is a standard + integral type(3.9.1 p7) - T is either char, wchar_t, bool + or either is_standard_signed_integral<T>::value or + is_standard_integral<T>::value is true. 
is_standard_float<T>::valueTrue if T is one of the + standard floating point types(3.9.1 p8) - float, double + or long double. 
is_standard_arithmetic<T>::valueTrue if T is a standard + arithmetic type(3.9.1 p8) - implies is_standard_integral + or is_standard_float is true. 
is_standard_fundamental<T>::valueTrue if T is a standard + arithmetic type or if T is void. 
is_extension_unsigned_integral<T>::valueTrue for compiler specific + unsigned integral types. 
is_extension_signed_integral<T>>:valueTrue for compiler specific + signed integral types. 
is_extension_integral<T>::valueTrue if either is_extension_unsigned_integral<T>::value + or is_extension_signed_integral<T>::value is true. 
is_extension_float<T>::valueTrue for compiler specific + floating point types. 
is_extension_arithmetic<T>::valueTrue if either is_extension_integral<T>::value + or is_extension_float<T>::value are true. 
 is_extension_fundamental<T>::valueTrue if either is_extension_arithmetic<T>::value + or is_void<T>::value are true. 
 is_unsigned_integral<T>::valueTrue if either is_standard_unsigned_integral<T>::value + or is_extention_unsigned_integral<T>::value are + true. 
is_signed_integral<T>::valueTrue if either is_standard_signed_integral<T>::value + or is_extention_signed_integral<T>>::value are + true. 
is_integral<T>::valueTrue if either is_standard_integral<T>::value + or is_extention_integral<T>::value are true. 
is_float<T>::valueTrue if either is_standard_float<T>::value + or is_extention_float<T>::value are true. 
is_arithmetic<T>::valueTrue if either is_integral<T>::value + or is_float<T>::value are true. 
is_fundamental<T>::valueTrue if either is_arithmetic<T>::value + or is_void<T>::value are true. 
+ +

 

+ +

Compound Types

+ +

The following will only ever be true for cv-unqualified types, +as defined by the Standard. 

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Expression

+

Description

+

Compiler

+
is_array<T>::valueTrue if T is an array type.

P

+
is_pointer<T>::valueTrue if T is a regular + pointer type - including function pointers - but + excluding pointers to member functions (3.9.2 p1 and 8.3.1).

P

+
is_member_pointer<T>::valueTrue if T is a pointer to a + non-static class member (3.9.2 p1 and 8.3.1).

P

+
is_reference<T>::valueTrue if T is a reference + type (3.9.2 p1 and 8.3.2).

P

+
is_class<T>::valueTrue if T is a class or + struct type.

PD

+
is_union<T>::valueTrue if T is a union type.

C

+
is_enum<T>::valueTrue if T is an enumerator + type.

C

+
is_compound<T>::valueTrue if T is any of the + above compound types.

PD

+
+ +

 

+ +

Object/Scalar Types

+ +

The following ignore any top level cv-qualifiers: if class_name<T>::value +is true then class_name<cv-qualified-T>::value +will also be true.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Expression

+

Description

+

Compiler

+
is_object<T>::valueTrue if T is not a reference + type, or a (possibly cv-qualified) void type.

P

+
is_standard_scalar<T>::valueTrue if T is a standard + arithmetic type, an enumerated type, a pointer or a + member pointer.

PD

+
is_extension_scalar<T>::valueTrue if T is an extentions + arithmetic type, an enumerated type, a pointer or a + member pointer.

PD

+
is_scalar<T>::valueTrue if T is an arithmetic + type, an enumerated type, a pointer or a member pointer.

PD

+
is_POD<T>::valueTrue if T is a "Plain + Old Data" type (see 3.9 p2&p3). Note that + although this requires compiler support to be correct in + all cases, if T is a scalar or an array of scalars then + we can correctly define T as a POD.

PC

+
is_empty<T>::valueTrue 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 - as a result will + not compile when passed an enumerated type unless there + is compiler support for is_enum.

PCD

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

PC

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

PC

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

PC

+
has_trivial_destructor<T>::valueTrue if T has a trivial + destructor - that is if T::~T() has no effect.

PC

+
+ +

 

+ +

Compiler Support Information

+ +

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

+ + + + + + + + + + + + + + +

P

+
Denotes that the class + requires support for partial specialisation 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, T is an enum, 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_enum' +for each user-defined enumeration type, '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.

+ +

Example code

+ +

Type-traits comes with two sample programs: type_traits_test.cpp tests the +type traits classes - mostly this is a test of your compiler's +support for the concepts used in the type traits implementation, +while algo_opt_examples.cpp +uses the type traits classes to "optimise" some +familiar standard library algorithms.

+ +

There are four algorithm examples in algo_opt_examples.cpp:

+ + + + + + + + + + + + + + + + + + +
opt::copy
+
If the copy operation can be + performed using memcpy then does so, otherwise uses a + regular element by element copy (c.f. std::copy).
opt::fill
+
If the fill operation can be + performed by memset, then does so, otherwise uses a + regular element by element assign. Also uses call_traits + to optimise how the parameters can be passed (c.f. + std::fill).
opt::destroy_array
+
If the type in the array has + a trivial destructor then does nothing, otherwise calls + destructors for all elements in the array - this + algorithm is the reverse of std::uninitialized_copy / std::uninitialized_fill.
opt::iter_swap
+
Determines whether the + iterator is a proxy-iterator: if it is then does a "slow + and safe" swap, otherwise calls std::swap on the + assumption that std::swap may be specialised for the + iterated type.
+ +

 

+ +
+ +

Revised 08th March 2000

+ +

© Copyright boost.org 2000. 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.

+ +

Based on contributions by Steve Cleary, Beman Dawes, Howard +Hinnant and John Maddock.

+ +

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

+ + diff --git a/utility.htm b/utility.htm new file mode 100644 index 0000000..2f0272e --- /dev/null +++ b/utility.htm @@ -0,0 +1,103 @@ + + + + +Header boost/utility.hpp Documentation + + + + +

c++boost.gif (8819 bytes)Header +boost/utility.hpp

+ +

The entire contents of the header <boost/utility.hpp> + are in namespace boost.

+ +

Contents

+ + +

Template functions next() and prior()

+ +

Certain data types, such as the C++ Standard Library's forward and +bidirectional iterators, do not provide addition and subtraction via operator+() +or operator-().  This means that non-modifying computation of the next or +prior value requires a temporary, even though operator++() or operator--() is +provided.  It also means that writing code like itr+1 inside a +template restricts the iterator category to random access iterators.

+ +

The next() and prior() functions provide a simple way around these problems:

+ +
+ +
template <class T>
+T next(T x) { return ++x; }
+
+template <class X>
+T prior(T x) { return --x; }
+ +
+ +

Usage is simple:

+ +
+ +
const std::list<T>::iterator p = get_some_iterator();
+const std::list<T>::iterator prev = boost::prior(p);
+ +
+ +

Contributed by Dave Abrahams.

+ +

Class noncopyable

+ +

Class noncopyable is a base class.  Derive your own class from noncopyable +when you want to prohibit copy construction and copy assignment.

+ +

Some objects, particularly those which hold complex resources like files or +network connections, have no sensible copy semantics.  Sometimes there are +possible copy semantics, but these would be of very limited usefulness and be +very difficult to implement correctly.  Sometimes you're implementing a class that doesn't need to be copied +just yet and you don't want to take the time to write the appropriate functions.  +Deriving from noncopyable will prevent the otherwise implicitly-generated +functions (which don't have the proper semantics) from becoming a trap for other programmers.

+ +

The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then +document why this is done.  But deriving from noncopyable is simpler +and clearer, and doesn't require additional documentation.

+ +

The program noncopyable_test.cpp can be +used to verify class noncopyable works as expected. It has have been run successfully under +GCC 2.95, Metrowerks +CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.

+ +

Contributed by Dave Abrahams.

+ +

Example

+
+
// inside one of your own headers ...
+#include <boost/utility.hpp>
+
+class ResourceLadenFileSystem : noncopyable {
+...
+
+ +

Rationale

+

Class noncopyable has protected constructor and destructor members to +emphasize that it is to be used only as a base class.  Dave Abrahams notes +concern about the effect on compiler optimization of adding (even trivial inline) +destructor declarations. He says "Probably this concern is misplaced, because +noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."

+
+

Revised  26 January, 2000 +

+

© Copyright boost.org 1999. 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.

+ +