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 @@ + + +
+ + + +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 |
+
|
+ 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& |
+
|
+ Defines a type that + represents a reference to type T. Use for functions that + would normally return a T&. | +1 + |
+
const T& |
+
|
+ Defines a type that + represents a constant reference to type T. Use for + functions that would normally return a const T&. | +1 + |
+
const T& |
+
|
+ Defines a type that + represents the "best" way to pass a parameter + of type T to a function. | +1,3 + |
+
Notes:
+ +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!).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).+ +
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 + |
+ - + |
+ - + |
+ - + |
+
+ +
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. + |
+
+ +
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){} + +};+ +
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.
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.
+ +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.
+ +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 @@ + + + + + + +
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 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; +}+
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.
+++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)+
++#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); + ...+
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:
++++
+- Both argument and result types are CopyConstructible [20.1.3].
+- Both argument and result types are Numeric, defined by
+std::numeric_limits<>::is_specialized
+ being true.- The argument can be converted to the result type using static_cast.
+
++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)+
++#include <boost/cast.hpp> +using namespace boost::cast; + +void ariane(double vx) +{ + ... + unsigned short dx = numeric_cast<unsigned short>(vx); + ... +}+
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 @@ + + + + + + +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 @@ + + + + + + +
![]() |
+ Home | +Libraries | +People | +FAQ | +More | +
Header | +Contents | +
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 +supplies (in namespace boost) several sets of templates:
+ +These templates define many global operators in terms of a minimal number of +fundamental 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.
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.
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.
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
template | +template will supply | +Requirements | +
operators<T> |
+ All the other <T> templates in this table. | +All the <T> requirements in this table. | +
operators<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> |
+ bool operator>(const T&, const T&) |
+ t<t1 . Return convertible to bool |
+
less_than_comparable<T,U> |
+ bool operator<=(const T&, const U&) |
+ t<u . Return convertible to bool+ t>u . Return convertible to bool |
+
equality_comparable<T> |
+ bool operator!=(const T&, const T&) |
+ t==t1 . Return convertible to bool |
+
equality_comparable<T,U> |
+ friend bool operator==(const U&, const T&) |
+ t==u . Return convertible to bool |
+
addable<T> |
+ T operator+(T, const T&) |
+ t+=t1 . Return convertible to T |
+
addable<T,U> |
+ T operator+(T, const U&) |
+ t+=u . Return convertible to T |
+
subtractable<T> |
+ T operator-(T, const T&) |
+ t-=t1 . Return convertible to T |
+
subtractable<T,U> |
+ T operator-(T, const U&) |
+ t-=u . Return convertible to T |
+
multipliable<T> |
+ T operator*(T, const T&) |
+ t*=t1 . Return convertible to T |
+
multipliable<T,U> |
+ T operator*(T, const U&) |
+ t*=u . Return convertible to T |
+
dividable<T> |
+ T operator/(T, const T&) |
+ t/=t1 . Return convertible to T |
+
dividable<T,U> |
+ T operator/(T, const U&) |
+ t/=u . Return convertible to T |
+
modable<T> |
+ T operator%(T, const T&) |
+ t%=t1 . Return convertible to T |
+
modable<T,U> |
+ T operator%(T, const U&) |
+ t%=u . Return convertible to T |
+
orable<T> |
+ T operator|(T, const T&) |
+ t|=t1 . Return convertible to T |
+
orable<T,U> |
+ T operator|(T, const U&) |
+ t|=u . Return convertible to T |
+
andable<T> |
+ T operator&(T, const T&) |
+ t&=t1 . Return convertible to T |
+
andable<T,U> |
+ T operator&(T, const U&) |
+ t&=u . Return convertible to T |
+
xorable<T> |
+ T operator^(T, const T&) |
+ t^=t1 . Return convertible to T |
+
xorable<T,U> |
+ T operator^(T, const U&) |
+ t^=u . Return convertible to T |
+
incrementable<T> |
+ T operator++(T& x, int) |
+ T temp(x); ++x; return temp; + Return convertible to T |
+
decrementable<T> |
+ T operator--(T& x, int) |
+ T temp(x); --x; return temp; + Return convertible to T |
+
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.
+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>; ++ +
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);+
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:
+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[]
).
+
T |
+ is the user-defined type for which the operations are + being supplied. | +
V |
+ is the type which the resulting dereferenceable
+ type "points to", or the value_type of the custom
+ iterator. |
+
D |
+ is the type used to index the resulting indexable
+ type or the difference_type of the custom iterator. |
+
P |
+ is a type which can be dereferenced to access V ,
+ or the pointer type of the custom iterator. |
+
R |
+ is the type returned by indexing the indexable
+ type or the reference type of the custom iterator. |
+
i |
+ is 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,x2 |
+ are objects of type T . |
+
n |
+ is 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.
+The dereference operator templates in this table all accept an optional +template parameter (not shown) to be used for base class +chaining. +
template | +template will supply | +Requirements | +
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 . |
+
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.).
template | +template will supply | +Requirements | +
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&) |
+ 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 |
+
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.
+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 @@ + + + + + + +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
Usage: "class_name<T>::type" performs +indicated transformation on type T.
+ +Expression. + |
+ Description. + |
+ Compiler. + |
+
remove_volatile<T>::type |
+ Creates a type the same as T + but with any top level volatile qualifier removed. For + example "volatile int" would become "int". | +P + |
+
remove_const<T>::type |
+ Creates a type the same as T + but with any top level const qualifier removed. For + example "const int" would become "int". | +P + |
+
remove_cv<T>::type |
+ Creates 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>::type |
+ If 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>::type |
+ If T is a reference type + then leaves T unchanged, otherwise converts T to a + reference type. For example "int&" remains + unchanged, but "double" becomes "double&". | +P + |
+
remove_bounds<T>::type |
+ If T is an array type then + removes the top level array qualifier from T, otherwise + leaves T unchanged. For example "int[2][3]" + becomes "int[3]". | +P + |
+
+ +
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).
+ +The following classes determine what cv-qualifiers are present +on a type (see 3.93).
+ +Expression. + |
+ Description. + |
+ Compiler. + |
+
is_const<T>::value |
+ True if type T is top-level + const qualified. | +P + |
+
is_volatile<T>::value |
+ True if type T is top-level + volatile qualified. | +P + |
+
is_same<T,U>::value |
+ True if T and U are the same + type. | +P + |
+
+ +
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>::value |
+ True only if T is void. | ++ |
is_standard_unsigned_integral<T>::value |
+ True 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>::value |
+ True 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>::value |
+ True 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>::value |
+ True if T is one of the + standard floating point types(3.9.1 p8) - float, double + or long double. | ++ |
is_standard_arithmetic<T>::value |
+ True 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>::value |
+ True if T is a standard + arithmetic type or if T is void. | ++ |
is_extension_unsigned_integral<T>::value |
+ True for compiler specific + unsigned integral types. | ++ |
is_extension_signed_integral<T>>:value |
+ True for compiler specific + signed integral types. | ++ |
is_extension_integral<T>::value |
+ True if either is_extension_unsigned_integral<T>::value + or is_extension_signed_integral<T>::value is true. | ++ |
is_extension_float<T>::value |
+ True for compiler specific + floating point types. | ++ |
is_extension_arithmetic<T>::value |
+ True if either is_extension_integral<T>::value + or is_extension_float<T>::value are true. | ++ |
is_extension_fundamental<T>::value |
+ True if either is_extension_arithmetic<T>::value + or is_void<T>::value are true. | ++ |
is_unsigned_integral<T>::value |
+ True if either is_standard_unsigned_integral<T>::value + or is_extention_unsigned_integral<T>::value are + true. | ++ |
is_signed_integral<T>::value |
+ True if either is_standard_signed_integral<T>::value + or is_extention_signed_integral<T>>::value are + true. | ++ |
is_integral<T>::value |
+ True if either is_standard_integral<T>::value + or is_extention_integral<T>::value are true. | ++ |
is_float<T>::value |
+ True if either is_standard_float<T>::value + or is_extention_float<T>::value are true. | ++ |
is_arithmetic<T>::value |
+ True if either is_integral<T>::value + or is_float<T>::value are true. | ++ |
is_fundamental<T>::value |
+ True if either is_arithmetic<T>::value + or is_void<T>::value are true. | ++ |
+ +
The following will only ever be true for cv-unqualified types, +as defined by the Standard.
+ +Expression + |
+ Description + |
+ Compiler + |
+
is_array<T>::value |
+ True if T is an array type. | +P + |
+
is_pointer<T>::value |
+ True 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>::value |
+ True if T is a pointer to a + non-static class member (3.9.2 p1 and 8.3.1). | +P + |
+
is_reference<T>::value |
+ True if T is a reference + type (3.9.2 p1 and 8.3.2). | +P + |
+
is_class<T>::value |
+ True if T is a class or + struct type. | +PD + |
+
is_union<T>::value |
+ True if T is a union type. | +C + |
+
is_enum<T>::value |
+ True if T is an enumerator + type. | +C + |
+
is_compound<T>::value |
+ True if T is any of the + above compound types. | +PD + |
+
+ +
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>::value |
+ True if T is not a reference + type, or a (possibly cv-qualified) void type. | +P + |
+
is_standard_scalar<T>::value |
+ True if T is a standard + arithmetic type, an enumerated type, a pointer or a + member pointer. | +PD + |
+
is_extension_scalar<T>::value |
+ True if T is an extentions + arithmetic type, an enumerated type, a pointer or a + member pointer. | +PD + |
+
is_scalar<T>::value |
+ True if T is an arithmetic + type, an enumerated type, a pointer or a member pointer. | +PD + |
+
is_POD<T>::value |
+ True 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>::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 - as a result will + not compile when passed an enumerated type unless there + is compiler support for is_enum. | +PCD + |
+
has_trivial_constructor<T>::value |
+ True if T has a trivial + default constructor - that is T() is equivalent to memset. | +PC + |
+
has_trivial_copy<T>::value |
+ True if T has a trivial copy + constructor - that is T(const T&) is equivalent to + memcpy. | +PC + |
+
has_trivial_assign<T>::value |
+ True if T has a trivial + assignment operator - that is if T::operator=(const T&) + is equivalent to memcpy. | +PC + |
+
has_trivial_destructor<T>::value |
+ True if T has a trivial + destructor - that is if T::~T() has no effect. | +PC + |
+
+ +
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.
+ +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 @@ + + + + +The entire contents of the header <boost/utility.hpp>
+ are in namespace boost
.
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 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.
+ +++ +// inside one of your own headers ... +#include <boost/utility.hpp> + +class ResourceLadenFileSystem : noncopyable { +...+
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.
+ +