diff --git a/Assignable.html b/Assignable.html deleted file mode 100644 index 557f4e7..0000000 --- a/Assignable.html +++ /dev/null @@ -1,116 +0,0 @@ - - -
--T - | --is type that is a model of Assignable - | -
-t - | --is an object of type T - | -
-u - | --is an object of type T or possibly const T - | -
-Name - | --Expression - | --Return type - | --Semantics - | -
---|---|---|---|
-Assignment - | --t = u - | --T& - | --t is equivalent to u - | -
Copyright © 2000 | -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) - |
- -
-Value type - | --X::value_type - | --The type of the object stored in a Collection. -If the Collection is mutable then -the value type must be Assignable. -Otherwise the value type must be CopyConstructible. - | -
-Iterator type - | --X::iterator - | --The type of iterator used to iterate through a Collection's - elements. The iterator's value type is expected to be the - Collection's value type. A conversion - from the iterator type to the const iterator type must exist. - The iterator type must be an InputIterator. - | -
-Const iterator type - | --X::const_iterator - | --A type of iterator that may be used to examine, but not to modify, - a Collection's elements. - | -
-Reference type - | --X::reference - | --A type that behaves like a reference to the Collection's value type. -[1] - | -
-Const reference type - | --X::const_reference - | --A type that behaves like a const reference to the Collection's value type. - | -
-Pointer type - | --X::pointer - | --A type that behaves as a pointer to the Collection's value type. - | -
-Distance type - | --X::difference_type - | --A signed integral type used to represent the distance between two - of the Collection's iterators. This type must be the same as - the iterator's distance type. - | -
-Size type - | --X::size_type - | --An unsigned integral type that can represent any nonnegative value - of the Collection's distance type. - | -
-X - | --A type that is a model of Collection. - | -
-a, b - | --Object of type X. - | -
-T - | --The value type of X. - | -
- -
-Name - | --Expression - | --Return type - | -
---|---|---|
-Beginning of range - | --a.begin() - | --iterator if a is mutable, const_iterator otherwise - | -
-End of range - | --a.end() - | --iterator if a is mutable, const_iterator otherwise - | -
-Size - | --a.size() - | --size_type - | --Empty Collection - | --a.empty() - | --Convertible to bool - | - -
-Swap - | --a.swap(b) - | --void - | -
-Name - | --Expression - | --Semantics - | --Postcondition - | -- |
---|---|---|---|
-Beginning of range - | --a.begin() - | --Returns an iterator pointing to the first element in the Collection. - | --a.begin() is either dereferenceable or past-the-end. It is - past-the-end if and only if a.size() == 0. - | -
-End of range - | --a.end() - | --Returns an iterator pointing one past the last element in the - Collection. - | --a.end() is past-the-end. - | -
-Size - | --a.size() - | --Returns the size of the Collection, that is, its number of elements. - | --a.size() >= 0 - | -
-Empty Collection - | --a.empty() - | --Equivalent to a.size() == 0. (But possibly faster.) - | -- - | -
-Swap - | --a.swap(b) - | --Equivalent to swap(a,b) - | -- - | -
-size() is at most linear in the Collection's -size. empty() is amortized constant time. -
-swap() is at most linear in the size of the two collections. -
-Valid range - | --For any Collection a, [a.begin(), a.end()) is a valid - range. - | -
-Range size - | --a.size() is equal to the distance from a.begin() to a.end(). - | -
-Completeness - | --An algorithm that iterates through the range [a.begin(), a.end()) - will pass through every element of a. - | -
-
-Name - | --Expression - | --Return type - | --Semantics - | -
---|---|---|---|
-Front - | --a.front() - | -
-reference if a is mutable, const_reference -otherwise. - |
--Equivalent to *(a.begin()). - | -
- -
-Name - | --Expression - | --Return type - | --Semantics - | -
---|---|---|---|
-Beginning of range - | --a.rbegin() - | --reverse_iterator if a is mutable, -const_reverse_iterator otherwise. - | --Equivalent to X::reverse_iterator(a.end()). - | -
-End of range - | --a.rend() - | --reverse_iterator if a is mutable, -const_reverse_iterator otherwise. - | --Equivalent to X::reverse_iterator(a.begin()). - | -
-Back - | --a.back() - | -
-reference if a is mutable, const_reference -otherwise. - |
--Equivalent to *(--a.end()). - | -
- -
-Name - | --Expression - | --Return type - | --Semantics - | -
---|---|---|---|
-Element Access - | --a[n] - | --reference if a is mutable, -const_reference otherwise. - | --Returns the nth element of the Collection. -n must be convertible to size_type. -Precondition: 0 <= n < a.size(). - | -
[1] - -The reference type does not have to be a real C++ reference. The -requirements of the reference type depend on the context within which -the Collection is being used. Specifically it depends on the -requirements the context places on the value type of the Collection. -The reference type of the Collection must meet the same requirements -as the value type. In addition, the reference objects must be -equivalent to the value type objects in the collection (which is -trivially true if they are the same object). Also, in a mutable -Collection, an assignment to the reference object must result in an -assignment to the object in the Collection (again, which is trivially -true if they are the same object, but non-trivial if the reference -type is a proxy class). - -
Copyright © 2000 | -Jeremy Siek, Univ.of Notre Dame and C++ Library & Compiler Group/SGI (jsiek@engr.sgi.com) - |
-T - | --is type that is a model of Copy Constructible - | -
-t - | --is an object of type T - | -
-u - | --is an object of type const T - | -
-Name - | --Expression - | --Return type - | --Semantics - | -
---|---|---|---|
-Copy constructor - | --T(t) - | --T - | --t is equivalent to T(t) - | -
-Copy constructor - | -
--T(u) -- |
--T - | --u is equivalent to T(u) - | -
-Destructor - | -
--t.~T() -- |
--T - | -- - | -
-Address Operator - | -
--&t -- |
--T* - | --denotes the address of t - | -
-Address Operator - | -
--&u -- |
--T* - | --denotes the address of u - | -
- template <class T> - struct CopyConstructibleConcept - { - void constraints() { - T a(b); // require copy constructor - T* ptr = &a; // require address of operator - const_constraints(a); - ignore_unused_variable_warning(ptr); - } - void const_constraints(const T& a) { - T c(a); // require const copy constructor - const T* ptr = &a; // require const address of operator - ignore_unused_variable_warning(c); - ignore_unused_variable_warning(ptr); - } - T b; - }; -- -
Copyright © 2000 | -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) - |
-X - | --A type that is a model of LessThanComparable - | -
-x, y, z - | --Object of type X - | -
-If operator< is a strict weak ordering, and if each equivalence class -has only a single element, then operator< is a total ordering. -
-Name - | --Expression - | --Type requirements - | --Return type - | -
---|---|---|---|
-Less - | --x < y - | -- - | --Convertible to bool - | -
-Name - | --Expression - | --Precondition - | --Semantics - | --Postcondition - | -
---|---|---|---|---|
-Less - | --x < y - | --x and y are in the domain of < - | -- - | -
-Irreflexivity - | --x < x must be false. - | -
-Antisymmetry - | --x < y implies !(y < x) [2] - | -
-Transitivity - | --x < y and y < z implies x < z [3] - | -
[1] -Only operator< is fundamental; the other inequality operators -are essentially syntactic sugar. -
[2] -Antisymmetry is a theorem, not an axiom: it follows from -irreflexivity and transitivity. -
[3] -Because of irreflexivity and transitivity, operator< always -satisfies the definition of a partial ordering. The definition of -a strict weak ordering is stricter, and the definition of a -total ordering is stricter still. -
Copyright © 2000 | -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) - |
I think that introducing Multi-Pass Input Iterator isn't the right -solution. Do you also want to define Multi-Pass Bidirectionnal Iterator -and Multi-Pass Random Access Iterator ? I don't, definitly. It only -confuses the issue. The problem lies into the existing hierarchy of -iterators, which mixes movabillity, modifiabillity and lvalue-ness, -and these are clearly independant. - -
The terms Forward, Bidirectionnal and Random Access are about -movabillity and shouldn't be used to mean anything else. In a -completly orthogonal way, iterators can be immutable, mutable, or -neither. Lvalueness of iterators is also orthogonal with -immutabillity. With these clean concepts, your Multi-Pass Input Iterator -is just called a Forward Iterator. - -
-Other translations are:
-std::Forward Iterator -> ForwardIterator & Lvalue Iterator
-std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue Iterator
-std::Random Access Iterator -> Random Access Iterator & Lvalue Iterator
-
-
-Note that in practice the only operation not allowed on my -Forward Iterator which is allowed on std::Forward Iterator is -&*it. I think that &* is rarely needed in generic code. - -
-reply by Jeremy Siek: - -
-The above analysis by Valentin is right on. Of course, there is
-the problem with backward compatibility. The current STL implementations
-are based on the old definition of Forward Iterator. The right course
-of action is to get Forward Iterator, etc. changed in the C++ standard.
-Once that is done we can drop Multi-Pass Input Iterator.
-
-
-
-
Copyright © 2000 | -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) - |
T | -is a type that is a model of OptionalPointee | -
t | -is an object of type T or possibly const T | -
Name | -Expression | -Return type | -Semantics | -|
---|---|---|---|---|
Value Access | -*t | -T& | -If the pointee is valid returns a reference to
- the pointee. - If the pointee is invalid the result is undefined. |
- - |
Value Access | -t->xyz | -T* | -If the pointee is valid returns a builtin pointer to the pointee. - If the pointee is invalid the result is undefined (It might not even return NULL). - |
- - |
Validity Test | - t - t != 0 - !!t - |
- bool | -If the pointee is valid returns true. - If the pointee is invalid returns false. |
- - |
Invalidity Test | - t == 0 - !t - |
- bool | -If the pointee is valid returns false. - If the pointee is invalid returns true. |
- - |
This concept does not define any particular semantic for relational operations, therefore,
-a type which models this concept might have either shallow or deep relational semantics.
-For instance, pointers, which are models of OptionalPointee, have shallow relational operators:
-comparisons of pointers do not involve comparisons of pointees.
-This makes sense for pointers because they have shallow copy semantics.
-But boost::optional<T>, on the other hand, which is also a model of OptionalPointee, has
-deep-copy and deep-relational semantics.
-If generic code is written for this concept, it is important not to use relational
-operators directly because the semantics might be different depending on the actual type.
-Still, the concept itsef can be used to define deep relational tests that can
-be used in generic code with any type which models OptionalPointee:
Equivalence relation:
-template<class OptionalPointee> -inline -bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y ) -{ - return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ; -} -template<class OptionalPointee> -struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool> -{ - bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const - { return equal_pointees(x,y) ; } -} ; --
The preceding generic function and function object have the following semantics:
-If both x and y have valid pointees, it compares values via (*x == *y)
.
-If only one has a valid pointee, returns false
.
-If both have invalid pointees, returns true
.
Less-than relation:
-template<class OptionalPointee> -inline -bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y ) -{ - return !y ? false : ( !x ? true : (*x) < (*y) ) ; -} -template<class OptionalPointee> -struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool> -{ - bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const - { return less_pointees(x,y) ; } -} ; --
The preceding generic function and function object have the following semantics:
-If y has an invalid pointee, returns false
.
-Else, if x has an invalid pointee, returns true
.
-Else, ( x and y have valid pointees), compares values via (*x <
-*y).
-All these functions and function
-objects are is implemented in compare_pointees.hpp
Notice that OptionalPointee does not imply aliasing (and optional<> for instance does not alias); -so direct usage of relational operators with the implied aliasing of shallow semantics --as with pointers- should not be used with generic code written for this concept.
- -Copyright © 2003 | -Fernando Cacciola, -based on the original concept developed by Augustus Saunders. - |
- ![]() |
-
- assert.hpp- |
-
- |
- The header <boost/assert.hpp> defines the macro BOOST_ASSERT, - which is similar to the standard assert macro defined in <cassert>. - The macro is intended to be used in Boost libraries. -
-By default, BOOST_ASSERT(expr) is equivalent to assert(expr).
-When the macro BOOST_DISABLE_ASSERTS is defined when <boost/assert.hpp> - is included, BOOST_ASSERT(expr) is defined as ((void)0). This - allows users to selectively disable BOOST_ASSERT without - affecting the definition of the standard assert.
-When the macro BOOST_ENABLE_ASSERT_HANDLER is defined when <boost/assert.hpp> - is included, BOOST_ASSERT(expr) evaluates expr and, if the - result is false, evaluates the expression
-::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, - __FILE__, __LINE__)
-assertion_failed is declared in <boost/assert.hpp> - as
--namespace boost -{ - -void assertion_failed(char const * expr, char const * function, char const * file, long line); - -} --
but it is never defined. The user is expected to supply an appropriate - definition.
-As is the case with <cassert>, <boost/assert.hpp> - can be included multiple times in a single translation unit. BOOST_ASSERT - will be redefined each time as specified above.
-
- Copyright © 2002 by Peter Dimov. Permission to copy, use, modify, sell and
- distribute this document is granted provided this copyright notice appears in
- all copies. This document is provided "as is" without express or implied
- warranty, and with no claim as to its suitability for any purpose.
The class template boost::base_from_member
provides
-a workaround for a class that needs to initialize a base class with a
-member. The class template is in boost/utility/base_from_member.hpp
-which is included in boost/utility.hpp.
There is test/example code in base_from_member_test.cpp.
- -When developing a class, sometimes a base class needs to be -initialized with a member of the current class. As a naïve -example:
- -- --#include <streambuf> // for std::streambuf -#include <ostream> // for std::ostream - -class fdoutbuf - : public std::streambuf -{ -public: - explicit fdoutbuf( int fd ); - //... -}; - -class fdostream - : public std::ostream -{ -protected: - fdoutbuf buf; -public: - explicit fdostream( int fd ) - : buf( fd ), std::ostream( &buf ) - {} - //... -}; -
This is undefined because C++'s initialization order mandates that -the base class is initialized before the member it uses. R. Samuel Klatchko developed a way -around this by using the initialization order in his favor. Base -classes are intialized in order of declaration, so moving the desired -member to another base class, that is initialized before the desired -base class, can ensure proper initialization.
- -A custom base class can be made for this idiom:
- -- --#include <streambuf> // for std::streambuf -#include <ostream> // for std::ostream - -class fdoutbuf - : public std::streambuf -{ -public: - explicit fdoutbuf( int fd ); - //... -}; - -struct fdostream_pbase -{ - fdoutbuf sbuffer; - - explicit fdostream_pbase( int fd ) - : sbuffer( fd ) - {} -}; - -class fdostream - : private fdostream_pbase - , public std::ostream -{ - typedef fdostream_pbase pbase_type; - typedef std::ostream base_type; - -public: - explicit fdostream( int fd ) - : pbase_type( fd ), base_type( &sbuffer ) - {} - //... -}; -
Other projects can use similar custom base classes. The technique -is basic enough to make a template, with a sample template class in -this library. The main template parameter is the type of the enclosed -member. The template class has several (explicit) constructor member -templates, which implicitly type the constructor arguments and pass them -to the member. The template class uses implicit copy construction and -assignment, cancelling them if the enclosed member is non-copyable.
- -Manually coding a base class may be better if the construction -and/or copying needs are too complex for the supplied template class, -or if the compiler is not advanced enough to use it.
- -Since base classes are unnamed, a class cannot have multiple (direct) -base classes of the same type. The supplied template class has an -extra template parameter, an integer, that exists solely to provide type -differentiation. This parameter has a default value so a single use of a -particular member type does not need to concern itself with the integer.
- -- --#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY -#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10 -#endif - -template < typename MemberType, int UniqueID = 0 > -class boost::base_from_member -{ -protected: - MemberType member; - - base_from_member(); - - template< typename T1 > - explicit base_from_member( T1 x1 ); - - template< typename T1, typename T2 > - base_from_member( T1 x1, T2 x2 ); - - //... - - template< typename T1, typename T2, typename T3, typename T4, - typename T5, typename T6, typename T7, typename T8, typename T9, - typename T10 > - base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, - T8 x8, T9 x9, T10 x10 ); -}; -
The class template has a first template parameter
-MemberType representing the type of the based-member.
-It has a last template parameter UniqueID, that is an
-int
, to differentiate between multiple base classes that use
-the same based-member type. The last template parameter has a default
-value of zero if it is omitted. The class template has a protected
-data member called member that the derived class can use
-for later base classes (or itself).
There is a default constructor and several constructor member -templates. These constructor templates can take as many arguments -(currently up to ten) as possible and pass them to a constructor of -the data member. Since C++ does not allow any way to explicitly state -the template parameters of a templated constructor, make sure that -the arguments are already close as possible to the actual type used in -the data member's desired constructor.
- -The BOOST_BASE_FROM_MEMBER_MAX_ARITY macro constant specifies -the maximum argument length for the constructor templates. The constant -may be overridden if more (or less) argument configurations are needed. The -constant may be read for code that is expandable like the class template and -needs to maintain the same maximum size. (Example code would be a class that -uses this class template as a base class for a member with a flexible set of -constructors.)
- -With the starting example, the fdoutbuf
sub-object needs
-to be encapsulated in a base class that is inheirited before
-std::ostream
.
- --#include <boost/utility/base_from_member.hpp> - -#include <streambuf> // for std::streambuf -#include <ostream> // for std::ostream - -class fdoutbuf - : public std::streambuf -{ -public: - explicit fdoutbuf( int fd ); - //... -}; - -class fdostream - : private boost::base_from_member<fdoutbuf> - , public std::ostream -{ - // Helper typedef's - typedef boost::base_from_member<fdoutbuf> pbase_type; - typedef std::ostream base_type; - -public: - explicit fdostream( int fd ) - : pbase_type( fd ), base_type( &member ) - {} - //... -}; -
The base-from-member idiom is an implementation detail, so it
-should not be visible to the clients (or any derived classes) of
-fdostream
. Due to the initialization order, the
-fdoutbuf
sub-object will get initialized before the
-std::ostream
sub-object does, making the former
-sub-object safe to use in the latter sub-object's construction. Since the
-fdoutbuf
sub-object of the final type is the only sub-object
-with the name "member," that name can be used
-unqualified within the final class.
The base-from-member class templates should commonly involve -only one base-from-member sub-object, usually for attaching a -stream-buffer to an I/O stream. The next example demonstrates how -to use multiple base-from-member sub-objects and the resulting -qualification issues.
- -- --#include <boost/utility/base_from_member.hpp> - -#include <cstddef> // for NULL - -struct an_int -{ - int y; - - an_int( float yf ); -}; - -class switcher -{ -public: - switcher(); - switcher( double, int * ); - //... -}; - -class flow_regulator -{ -public: - flow_regulator( switcher &, switcher & ); - //... -}; - -template < unsigned Size > -class fan -{ -public: - explicit fan( switcher ); - //... -}; - -class system - : private boost::base_from_member<an_int> - , private boost::base_from_member<switcher> - , private boost::base_from_member<switcher, 1> - , private boost::base_from_member<switcher, 2> - , protected flow_regulator - , public fan<6> -{ - // Helper typedef's - typedef boost::base_from_member<an_int> pbase0_type; - typedef boost::base_from_member<switcher> pbase1_type; - typedef boost::base_from_member<switcher, 1> pbase2_type; - typedef boost::base_from_member<switcher, 2> pbase3_type; - - typedef flow_regulator base1_type; - typedef fan<6> base2_type; - -public: - system( double x ); - //... -}; - -system::system( double x ) - : pbase0_type( 0.2 ) - , pbase1_type() - , pbase2_type( -16, &this->pbase0_type::member ) - , pbase3_type( x, static_cast<int *>(NULL) ) - , base1_type( pbase3_type::member, pbase1_type::member ) - , base2_type( pbase2_type::member ) -{ - //... -} -
The final class has multiple sub-objects with the name
-"member," so any use of that name needs qualification by
-a name of the appropriate base type. (Using typedef
s
-ease mentioning the base types.) However, the fix introduces a new
-problem when a pointer is needed. Using the address operator with
-a sub-object qualified with its class's name results in a pointer-to-member
-(here, having a type of an_int boost::base_from_member<an_int,
-0> :: *
) instead of a pointer to the member (having a type of
-an_int *
). The new problem is fixed by qualifying the
-sub-object with "this->
," and is needed just
-for pointers, and not for references or values.
There are some argument conversions in the initialization. The
-constructor argument for pbase0_type
is converted from
-double
to float
. The first constructor
-argument for pbase2_type
is converted from int
-to double
. The second constructor argument for
-pbase3_type
is a special case of necessary conversion; all
-forms of the null-pointer literal in C++ also look like compile-time
-integral expressions, so C++ always interprets such code as an integer
-when it has overloads that can take either an integer or a pointer. The
-last conversion is necessary for the compiler to call a constructor form
-with the exact pointer type used in switcher
's constructor.
Revised: 28 August 2004
- -Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and distribution -are subject to the Boost Software License, Version 1.0. (See accompanying -file LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
- - - diff --git a/base_from_member_test.cpp b/base_from_member_test.cpp deleted file mode 100644 index 89328e4..0000000 --- a/base_from_member_test.cpp +++ /dev/null @@ -1,595 +0,0 @@ -// Boost test program for base-from-member class templates -----------------// - -// Copyright 2001, 2003 Daryle Walker. Use, modification, and distribution are -// subject to the Boost Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or a copy atAll 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 either partial -specialization or member templates, 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. In addition if -only member templates and not partial template specialisation is -support by the compiler (for example Visual C++ 6) then -call_traits can not be used with array types (although it can be -used to solve the reference to reference problem).
- -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<typename Operation::second_argument_type, typename Operation::result_type> -{ -protected: - Operation op; - typename Operation::first_argument_type value; -public: - binder1st(const Operation& x, const typename Operation::first_argument_type& y); - typename Operation::result_type operator()(const typename 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:
typename Operation::result_type operator()(typename call_traits<typename 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. Note that the function arguments to -make_pair are not expressed in terms of call_traits: doing so -would prevent template argument deduction from functioning.
- -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 fill_example.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.
- -Note that the function arguments to fill are not expressed in -terms of call_traits: doing so would prevent template argument -deduction from functioning. Instead fill acts as a "thin -wrapper" that is there to perform template argument -deduction, the compiler will optimise away the call to fill all -together, replacing it with the call to filler<>::do_fill, -which does use call_traits.
- -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(typename call_traits<T>::value_type t); -}; - -template <class T> -void A<T>::foo(typename call_traits<T>::value_type t) -{ - typename 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 01 September 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.yahoogroups.com/list/boost.
- -.
- -- -
- - diff --git a/call_traits_test.cpp b/call_traits_test.cpp deleted file mode 100644 index f5ac3a2..0000000 --- a/call_traits_test.cpp +++ /dev/null @@ -1,466 +0,0 @@ -// boost::compressed_pair test program - -// (C) Copyright John Maddock 2000. -// Use, modification and distribution are subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt). - - -// standalone test program for
- ![]() |
-
- checked_delete.hpp- |
-
- |
- The header <boost/checked_delete.hpp> defines two - function templates, checked_delete and checked_array_delete, - and two class templates, checked_deleter and checked_array_deleter. -
-The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be - deleted with a delete-expression. When the class has a non-trivial - destructor, or a class-specific operator delete, the behavior is undefined. - Some compilers issue a warning when an incomplete type is deleted, but - unfortunately, not all do, and programmers sometimes ignore or disable - warnings.
-A particularly troublesome case is when a smart pointer's destructor, such as - boost::scoped_ptr<T>::~scoped_ptr, is instantiated with an - incomplete type. This can often lead to silent, hard to track failures.
-The supplied function and class templates can be used to prevent these problems, - as they require a complete type, and cause a compilation error otherwise.
--namespace boost -{ - -template<class T> void checked_delete(T * p); -template<class T> void checked_array_delete(T * p); -template<class T> struct checked_deleter; -template<class T> struct checked_array_deleter; - -} --
--- Requires: T must be a complete type. The expression delete p - must be well-formed. -
-- Effects: delete p; -
-
--- Requires: T must be a complete type. The expression delete [] p - must be well-formed. -
-- Effects: delete [] p; -
-
-template<class T> struct checked_deleter -{ - typedef void result_type; - typedef T * argument_type; - void operator()(T * p) const; -}; --
--- Requires: T must be a complete type. The expression delete p - must be well-formed. -
-- Effects: delete p; -
-
-template<class T> struct checked_array_deleter -{ - typedef void result_type; - typedef T * argument_type; - void operator()(T * p) const; -}; --
--- Requires: T must be a complete type. The expression delete [] p - must be well-formed. -
-- Effects: delete [] p; -
-
- The function templates checked_delete and checked_array_delete - were originally part of <boost/utility.hpp>, and the - documentation acknowledged Beman Dawes, Dave Abrahams, Vladimir Prus, Rainer - Deyke, John Maddock, and others as contributors. -
-
-
- Copyright © 2002 by Peter Dimov. 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.
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 base-class 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); - - compressed_pair& operator=(const compressed_pair&); - - 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 if either member is a POD type, then that member is not - zero-initialized by the compressed_pair default constructor: it's up to you to - supply an initial value for these types if you want them to have a default - value.
-Note that compressed_pair can not be instantiated if either of the template - arguments is a union type, unless there is compiler support for - boost::is_union, or if boost::is_union is specialised for the union type.
-Finally, a word of caution for Visual C++ 6 users: if either argument is an - empty type, then assigning to that member will produce memory corruption, - unless the empty type has a "do nothing" assignment operator defined. This is - due to a bug in the way VC6 generates implicit assignment operators.
-Revised 08 May 2001
-© 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.yahoogroups.com/list/boost.
-- - diff --git a/compressed_pair_test.cpp b/compressed_pair_test.cpp deleted file mode 100644 index 7687f0a..0000000 --- a/compressed_pair_test.cpp +++ /dev/null @@ -1,395 +0,0 @@ -// boost::compressed_pair test program - -// (C) Copyright John Maddock 2000. -// Use, modification and distribution are subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt). - -// standalone test program for