From 703a4bf752c153ccbf3688c9841295d234a4f085 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Fri, 5 Nov 2021 21:50:00 -0300 Subject: [PATCH] Transcribe documentation to quickbook --- Assignable.html | 118 +- Collection.html | 543 +-------- CopyConstructible.html | 194 +-- LessThanComparable.html | 219 +--- MultiPassInputIterator.html | 104 +- OptionalPointee.html | 178 +-- call_traits.htm | 762 +----------- checked_delete.html | 20 +- compressed_pair.htm | 21 +- doc/BOOST_BINARY.qbk | 74 ++ doc/base_from_member.qbk | 304 ++--- doc/call_traits.qbk | 432 +++++++ doc/compressed_pair.qbk | 99 +- doc/declval.qbk | 114 -- doc/in_place_factory.qbk | 300 +++++ doc/operators.qbk | 1986 +++++++++++++++++++++++++++++++ doc/result_of.qbk | 407 +++++++ doc/string_ref.qbk | 172 --- doc/string_view.qbk | 199 ++++ doc/value_init.qbk | 564 +++++++++ enable_if.html | 20 +- identity_type/index.html | 2 +- in_place_factories.html | 313 +---- index.html | 65 +- iterator_adaptors.htm | 18 +- operators.htm | 2235 +---------------------------------- throw_exception.html | 14 +- utility.htm | 598 +--------- value_init.htm | 523 +------- 29 files changed, 4401 insertions(+), 6197 deletions(-) create mode 100644 doc/BOOST_BINARY.qbk create mode 100644 doc/call_traits.qbk delete mode 100644 doc/declval.qbk create mode 100644 doc/in_place_factory.qbk create mode 100644 doc/operators.qbk create mode 100644 doc/result_of.qbk delete mode 100644 doc/string_ref.qbk create mode 100644 doc/string_view.qbk create mode 100644 doc/value_init.qbk diff --git a/Assignable.html b/Assignable.html index d3b3157..942d491 100644 --- a/Assignable.html +++ b/Assignable.html @@ -1,109 +1,19 @@ - - - - - - Assignable + Boost.Utility + - - - C++ Boost
- -

Assignable

- -

Description

- -

A type is Assignable if it is possible to assign one object of the type - to another object of that type.

- -

Notation

- - - - - - - - - - - - - - - - - - - -
Tis type that is a model of Assignable
tis an object of type T
uis an object of type T or possibly const - T
- -

Definitions

- -

Valid expressions

- - - - - - - - - - - - - - - - - - - - - -
NameExpressionReturn typeSemantics
Assignmentt = uT&t is equivalent to u
- -

Models

- - - -

See also

- -

DefaultConstructible - and CopyConstructible

-
- -

Valid HTML 4.01 Transitional

- -

Revised - 05 December, 2006

- - - - - - - -
Copyright © 2000Jeremy Siek, Univ.of - Notre Dame (jsiek@lsc.nd.edu)
- -

Distributed under 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)

+ +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/Collection.html b/Collection.html index b92ddd6..942d491 100644 --- a/Collection.html +++ b/Collection.html @@ -1,534 +1,19 @@ - - - - - - Collection + Boost.Utility + - - -

boost logo
- Collection

- -

Description

- -

A Collection is a concept similar to the STL Container concept. A - Collection provides iterators for accessing a range of elements and - provides information about the number of elements in the Collection. - However, a Collection has fewer requirements than a Container. The - motivation for the Collection concept is that there are many useful - Container-like types that do not meet the full requirements of Container, - and many algorithms that can be written with this reduced set of - requirements. To summarize the reduction in requirements:

- - Because of the reduced requirements, some care must be taken when - writing code that is meant to be generic for all Collection types. In - particular, a Collection object should be passed by-reference since - assumptions can not be made about the behaviour of the copy constructor. - -

Associated types

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Value typeX::value_typeThe 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 typeX::iteratorThe 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 typeX::const_iteratorA type of iterator that may be used to examine, but - not to modify, a Collection's elements.
Reference typeX::referenceA type that behaves like a reference to the - Collection's value type. [1]
Const reference typeX::const_referenceA type that behaves like a const reference to the - Collection's value type.
Pointer typeX::pointerA type that behaves as a pointer to the Collection's - value type.
Distance typeX::difference_typeA 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 typeX::size_typeAn unsigned integral type that can represent any - nonnegative value of the Collection's distance type.
- -

Notation

- - - - - - - - - - - - - - - - - - - -
XA type that is a model of Collection.
a, bObject of type X.
TThe value type of X.
- -

Valid expressions

- -

The following expressions must be valid.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameExpressionReturn type
Beginning of rangea.begin()iterator if a is mutable, - const_iterator otherwise
End of rangea.end()iterator if a is mutable, - const_iterator otherwise
Sizea.size()size_type
Empty Collectiona.empty()Convertible to bool
Swapa.swap(b)void
- -

Expression semantics

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameExpressionSemanticsPostcondition
Beginning of rangea.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 rangea.end()Returns an iterator pointing one past the last element - in the Collection.a.end() is past-the-end.
Sizea.size()Returns the size of the Collection, that is, its - number of elements.a.size() >= 0
Empty Collectiona.empty()Equivalent to a.size() == 0. (But possibly - faster.) 
Swapa.swap(b)Equivalent to swap(a,b) 
- -

Complexity guarantees

- -

begin() and end() are amortized constant time.

- -

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.

- -

Invariants

- - - - - - - - - - - - - - - - - - - -
Valid rangeFor any Collection a, [a.begin(), - a.end()) is a valid range.
Range sizea.size() is equal to the distance from - a.begin() to a.end().
CompletenessAn algorithm that iterates through the range - [a.begin(), a.end()) will pass through every element of - a.
- -

Models

- - - -

Collection Refinements

- -

There are quite a few concepts that refine the Collection concept, - similar to the concepts that refine the Container concept. Here is a brief - overview of the refining concepts.

- -

ForwardCollection

- -

The elements are arranged in some order that does not change - spontaneously from one iteration to the next. As a result, a - ForwardCollection is EqualityComparable - and LessThanComparable. - In addition, the iterator type of a ForwardCollection is a - MultiPassInputIterator which is just an InputIterator with the added - requirements that the iterator can be used to make multiple passes through - a range, and that if it1 == it2 and it1 is - dereferenceable then ++it1 == ++it2. The ForwardCollection also - has a front() method.

- - - - - - - - - - - - - - - - - - - - - -
NameExpressionReturn typeSemantics
Fronta.front()reference if a is mutable,
- const_reference otherwise.
Equivalent to *(a.begin()).
- -

ReversibleCollection

- -

The container provides access to iterators that traverse in both - directions (forward and reverse). The iterator type must meet all of the - requirements of BidirectionalIterator - except that the reference type does not have to be a real C++ reference. - The ReversibleCollection adds the following requirements to those of - ForwardCollection.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameExpressionReturn typeSemantics
Beginning of rangea.rbegin()reverse_iterator if a is mutable, - const_reverse_iterator otherwise.Equivalent to - X::reverse_iterator(a.end()).
End of rangea.rend()reverse_iterator if a is mutable, - const_reverse_iterator otherwise.Equivalent to - X::reverse_iterator(a.begin()).
Backa.back()reference if a is mutable,
- const_reference otherwise.
Equivalent to *(--a.end()).
- -

SequentialCollection

- -

The elements are arranged in a strict linear order. No extra methods are - required.

- -

RandomAccessCollection

- -

The iterators of a RandomAccessCollection satisfy all of the - requirements of RandomAccessIterator - except that the reference type does not have to be a real C++ reference. In - addition, a RandomAccessCollection provides an element access operator.

- - - - - - - - - - - - - - - - - - - - - -
NameExpressionReturn typeSemantics
Element Accessa[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().
- -

Notes

- -

[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).

- -

See also

- -

Container

-
- -

Valid HTML 4.01 Transitional

- -

Revised - 05 - December, 2006

- - - - - - - -
Copyright © 2000Jeremy - Siek, Univ.of Notre Dame and C++ Library & Compiler Group/SGI - (jsiek@engr.sgi.com)
- -

Distributed under 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)

+ +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/CopyConstructible.html b/CopyConstructible.html index 6a7ce65..942d491 100644 --- a/CopyConstructible.html +++ b/CopyConstructible.html @@ -1,185 +1,19 @@ - - - - - - Copy Constructible + Boost.Utility + - - - C++ Boost
- -

Copy Constructible

- -

Description

- -

A type is Copy Constructible if it is possible to copy objects of that - type.

- -

Notation

- - - - - - - - - - - - - - - - - - - -
Tis type that is a model of Copy Constructible
tis an object of type T
uis an object of type const T
- -

Definitions

- -

Valid expressions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameExpressionReturn typeSemantics
Copy constructorT(t)Tt is equivalent to T(t)
Copy constructor -
-T(u)
-
-
Tu 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
- -

Models

- - - -

Concept Checking Class

-
-  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;
-  };
-
- -

See also

- -

Default - Constructible and Assignable

-
- -

Valid HTML 4.01 Transitional

- -

Revised - 05 - December, 2006

- - - - - - - -
Copyright © 2000Jeremy Siek, Univ.of - Notre Dame (jsiek@lsc.nd.edu)
- -

Distributed under 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)

+ +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/LessThanComparable.html b/LessThanComparable.html index 15b938f..942d491 100644 --- a/LessThanComparable.html +++ b/LessThanComparable.html @@ -1,210 +1,19 @@ - - - - - - - - LessThanComparable + Boost.Utility + - - - C++ Boost
- -

LessThanComparable

- -

Description

- -

A type is LessThanComparable if it is ordered: it must be possible to - compare two objects of that type using operator<, and - operator< must be a strict weak ordering relation.

- -

Refinement of

- -

Associated types

- -

Notation

- - - - - - - - - - - - - -
XA type that is a model of LessThanComparable
x, y, zObject of type X
- -

Definitions

- -

Consider the relation !(x < y) && !(y < x). If - this relation is transitive (that is, if !(x < y) && !(y - < x) && !(y < z) && !(z < y) implies !(x - < z) && !(z < x)), then it satisfies the mathematical - definition of an equivalence relation. In this case, operator< - is a strict weak ordering.

- -

If operator< is a strict weak ordering, and if each - equivalence class has only a single element, then operator< is - a total ordering.

- -

Valid expressions

- - - - - - - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Lessx < y Convertible to bool
- -

Expression semantics

- - - - - - - - - - - - - - - - - - - - - - - -
NameExpressionPreconditionSemanticsPostcondition
Lessx < yx and y are in the domain of - < 
- -

Complexity guarantees

- -

Invariants

- - - - - - - - - - - - - - - - - - - -
Irreflexivityx < x must be false.
Antisymmetryx < y implies !(y < x) [2]
Transitivityx < y and y < z implies x - < z [3]
- -

Models

- - - -

Notes

- -

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

- -

See also

- -

EqualityComparable, - StrictWeakOrdering
-

-
- -

Valid HTML 4.01 Transitional

- -

Revised - 05 - December, 2006

- - - - - - - -
Copyright © 2000Jeremy Siek, Univ.of - Notre Dame (jsiek@lsc.nd.edu)
- -

Distributed under 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)

+ +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/MultiPassInputIterator.html b/MultiPassInputIterator.html index e331ca3..942d491 100644 --- a/MultiPassInputIterator.html +++ b/MultiPassInputIterator.html @@ -1,95 +1,19 @@ - - - - - - MultiPassInputIterator + Boost.Utility + - - - C++ Boost
- -

Multi-Pass Input Iterator

- -

This concept is a refinement of Input Iterator, adding - the requirements that the iterator can be used to make multiple passes - through a range, and that if it1 == it2 and it1 is - dereferenceable then ++it1 == ++it2. The Multi-Pass Input Iterator - is very similar to the Forward Iterator. - The only difference is that a Forward Iterator - requires the reference type to be value_type&, - whereas MultiPassInputIterator is like Input Iterator in that - the reference type merely has to be convertible to - value_type.

- -

Design Notes

- -

comments by Valentin Bonnard:

- -

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.

-
- -

Valid HTML 4.01 Transitional

- -

Revised - 05 - December, 2006

- - - - - - - -
Copyright © 2000Jeremy Siek, Univ.of - Notre Dame (jsiek@lsc.nd.edu)
- -

Distributed under 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)

+ +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/OptionalPointee.html b/OptionalPointee.html index c3c7e44..942d491 100644 --- a/OptionalPointee.html +++ b/OptionalPointee.html @@ -1,159 +1,19 @@ - - -OptionalPointee Concept - - -C++ Boost - -
-

Concept: OptionalPointee

- -

Description

-A type is a model of OptionalPointee if it points to (or refers to) a value -that may not exist. That is, if it has a pointee which might be valid -(existent) or invalid (inexistent); and it is possible to test whether the -pointee is valid or not. -This model does not imply pointer semantics: i.e., it does not imply shallow copy nor -aliasing. -

Notation

- - - - - - - - - -
T is a type that is a model of OptionalPointee
t is an object of type T or possibly const T
-

Definitions

-

Valid expressions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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 bool(t) bool If the pointee is valid returns true.
- If the pointee is invalid returns false.
Invalidity Test !t bool If the pointee is valid returns false.
- If the pointee is invalid returns true.
- - -

Models

- - - -
-

OptionalPointee and relational operations

-

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.

- -

Acknowledgements

-

Based on the original concept developed by Augustus Saunders. - -
-

-
- - -
Copyright © 2003 -Fernando Cacciola -
- -

Distributed under the Boost Software License, Version 1.0. See -www.boost.org/LICENSE_1_0.txt

- - - + + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
+ + diff --git a/call_traits.htm b/call_traits.htm index b4fe3ee..cda1f2d 100644 --- a/call_traits.htm +++ b/call_traits.htm @@ -1,755 +1,19 @@ - - - - -Call Traits + Boost.Utility + - - - -

Header -<boost/call_traits.hpp>

- -

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

- -

The template class call_traits<T> encapsulates the -"best" method to pass a parameter of some type T to or -from a function, and consists of a collection of typedefs defined -as in the table below. The purpose of call_traits is to ensure -that problems like "references to references" -never occur, and that parameters are passed in the most efficient -manner possible (see examples). In each -case if your existing practice is to use the type defined on the -left, then replace it with the call_traits defined type on the -right.

- -

Note that for compilers that do not support 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
- (return by value)

-

call_traits<T>::value_type

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

2

-

T&
- (return value)

-

call_traits<T>::reference

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

1

-

const - T&
- (return value)

-

call_traits<T>::const_reference

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

1

-

const - T&
- (function parameter)

-

call_traits<T>::param_type

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

1,3

-
- -

Notes:

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

 

- -

Copy constructibility

- -

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

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

To:

-
From:

T

-

value_type

-

reference

-

const_reference

-

param_type

-
T

?

-

?

-

Y

-

Y

-

Y

-
value_type

?

-

?

-

N

-

N

-

Y

-
reference

?

-

?

-

Y

-

Y

-

Y

-
const_reference

?

-

N

-

N

-

Y

-

Y

-
param_type

?

-

?

-

N

-

N

-

Y

-
- -

 

- -

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

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

To:

-
From:

T

-

value_type

-

reference

-

const_reference

-

param_type

-
T

Y

-

Y

-

-

-

-

-

-

-
value_type

Y

-

Y

-

-

-

-

-

-

-
reference

Y

-

Y

-

-

-

-

-

-

-
const_reference

Y

-

Y

-

-

-

-

-

-

-
param_type

Y

-

Y

-

-

-

-

-

-

-
- -

 

- -

Examples

- -

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

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

Call_traits type:

-

Original type T

-

value_type

-

reference

-

const_reference

-

param_type

-

Applies to:

-

myclass

-

myclass

-

myclass&

-

const - myclass&

-

myclass - const&

-

All user - defined types.

-

int

-

int

-

int&

-

const - int&

-

int const

-

All small - built-in types.

-

int*

-

int*

-

int*&

-

int*const&

-

int* const

-

All - pointer types.

-

int&

-

int&

-

int&

-

const - int&

-

int&

-

All - reference types.

-

const int&

-

const - int&

-

const - int&

-

const - int&

-

const - int&

-

All - constant-references.

-

int[3]

-

const int*

-

int(&)[3]

-

const int(&)[3]

-

const int* - const

-

All array - types.

-

const int[3]

-

const int*

-

const int(&)[3]

-

const int(&)[3]

-

const int* - const

-

All - constant-array types.

-
- -

 

- -

Example 1:

- -

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

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

Example 2 (the reference to reference -problem):

- -

Consider the definition of std::binder1st:

- -
template <class Operation> 
-class binder1st : 
-   public unary_function<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.

- -

Example 3 (the make_pair problem):

- -

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

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

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

- -

Example 4 (optimising fill):

- -

The call_traits template will "optimize" the passing -of a small built-in type as a function parameter, this mainly has -an effect when the parameter is used within a loop body. In the -following example (see 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.

- -

Rationale

- -

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

- -

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

- -

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

- -

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

- -

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

- -

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

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

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

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

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

- -
template <class T>
-struct A
-{
-   void foo(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).

- + +Automatic redirection failed, please go to +./doc/html/utility/utilities/call_traits.html
- -

Revised 01 September 2000

- -

- Copyright 2000 Steve Cleary, Beman Dawes, Howard - Hinnant and John Maddock.
- 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 - ). -

+ + Boost.Utility
+
+ Distributed under 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)
+
+
- diff --git a/checked_delete.html b/checked_delete.html index 1b93256..7a60faf 100644 --- a/checked_delete.html +++ b/checked_delete.html @@ -1,15 +1,19 @@ - - -Automatic redirection + Boost.Utility + Automatic redirection failed, please go to -checked_delete.html
-

© Copyright Beman Dawes, 2001

-

Distributed under the Boost Software License, Version 1.0. (See accompanying -file LICENSE_1_0.txt or copy -at www.boost.org/LICENSE_1_0.txt)

+../core/doc/html/core/checked_delete.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/compressed_pair.htm b/compressed_pair.htm index 0b99bf7..9937a44 100644 --- a/compressed_pair.htm +++ b/compressed_pair.htm @@ -1,16 +1,19 @@ - - - - + Boost.Utility + Automatic redirection failed, please go to -doc/html/compressed_pair.html +./doc/html/utility/utilities/compressed_pair.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/doc/BOOST_BINARY.qbk b/doc/BOOST_BINARY.qbk new file mode 100644 index 0000000..4b207ce --- /dev/null +++ b/doc/BOOST_BINARY.qbk @@ -0,0 +1,74 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / Distributed under 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) + /] + +[/===============] +[#sec:BOOST_BINARY] +[section Binary Integer Literals] +[/===============] + +[heading Introduction] + +The macro `BOOST_BINARY` is used for the representation of binary +literals. It takes as an argument a binary number arranged as an +arbitrary amount of 1s and 0s in groupings of length 1 to 8, with +groups separated by spaces. The macro serves as a replacement for +[@https://en.cppreference.com/w/cpp/language/integer_literal binary integer literals], +adopted in C++14. + +The type of the literal yielded is determined by the same rules as +those of [@https://en.cppreference.com/w/cpp/language/integer_literal hex and octal literals]. +By implementation, this macro expands directly to an octal literal during preprocessing, so +there is no overhead at runtime and the result is usable in any place that an octal literal +would be. + +In order to directly support binary literals with suffixes, +additional macros of the form `BOOST_BINARY_XXX` are also +provided, where `XXX` is a standard integer suffix in all capital +letters. + +In addition, LL and ULL suffixes may be used for representing +`long long` and `unsigned long long` types in compilers which provide +them as an extension. + +The `BOOST_BINARY` family of macros resides in the header +[@../../../include/boost/utility/binary.hpp ]. + +[heading Example] + +``` +void foo( int ); + +void foo( unsigned long ); + +void bar() +{ + int value1 = BOOST_BINARY( 100 111000 01 1 110 ); + + unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned long + + long long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported + + __assert__( BOOST_BINARY( 10010 ) + & BOOST_BINARY( 11000 ) + == BOOST_BINARY( 10000 ) + ); + + foo( BOOST_BINARY( 1010 ) ); // calls the first foo + + foo( BOOST_BINARY_LU( 1010 ) ); // calls the second foo +} +``` + +[heading Acknowledgments] + +Contributed by Matt Calabrese. + +[endsect] + + + + diff --git a/doc/base_from_member.qbk b/doc/base_from_member.qbk index 9801214..d17559d 100644 --- a/doc/base_from_member.qbk +++ b/doc/base_from_member.qbk @@ -1,5 +1,6 @@ [/ Copyright 2001, 2003, 2004, 2012 Daryle Walker. + Copyright (c) 2021, Alan Freitas Distributed under the Boost Software License, Version 1.0. @@ -7,48 +8,43 @@ or copy at http://boost.org/LICENSE_1_0.txt ] -[article Base_From_Member - [quickbook 1.5] - [authors [Walker, Daryle]] - [copyright 2001, 2003, 2004, 2012 Daryle Walker] - [license - Distributed under 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]) - ] -] +[section:base_from_member Base from Member] +[block''''''] -[section Rationale] +[heading Introduction] +The class templates __base_from_member__ support the base-from-member idiom. When developing a class, sometimes a base class needs to be initialized with a member of the current class. As a na\u00EFve example: - #include /* for std::streambuf */ - #include /* for std::ostream */ +``` +#include /* for std::streambuf */ +#include /* for std::ostream */ - class fdoutbuf - : public std::streambuf - { - public: - explicit fdoutbuf( int fd ); - //... - }; +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 ) {} - //... - }; +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. [@http://www.moocat.org 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 +order in his favor. Base classes are initialized 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. @@ -58,7 +54,7 @@ A custom base class can be made for this idiom: #include /* for std::ostream */ class fdoutbuf - : public std::streambuf + : public __std_streambuf__ { public: explicit fdoutbuf( int fd ); @@ -75,10 +71,10 @@ A custom base class can be made for this idiom: class fdostream : private fdostream_pbase - , public std::ostream + , public __std_ostream__ { typedef fdostream_pbase pbase_type; - typedef std::ostream base_type; + typedef __std_ostream__ base_type; public: explicit fdostream( int fd ) @@ -104,9 +100,8 @@ 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. -[endsect] -[section Synopsis] +[heading Synopsis] #include /* exposition only */ @@ -115,41 +110,41 @@ type does not need to concern itself with the integer. #endif template < typename MemberType, int UniqueID = 0 > - class boost::base_from_member + class __boost_base_from_member__ { protected: MemberType member; #if ``['C++11 is in use]`` template< typename ...T > - explicit constexpr base_from_member( T&& ...x ) - noexcept( std::is_nothrow_constructible::value ); + explicit constexpr __base_from_member__( T&& ...x ) + noexcept( __std_is_nothrow_constructible__::value ); #else - base_from_member(); + __base_from_member__(); template< typename T1 > - explicit base_from_member( T1 x1 ); + explicit __base_from_member__( T1 x1 ); template< typename T1, typename T2 > - base_from_member( T1 x1, T2 x2 ); + __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, + __base_from_member__( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8, T9 x9, T10 x10 ); #endif }; template < typename MemberType, int UniqueID > - class base_from_member + class __base_from_member__ { protected: MemberType& member; - explicit constexpr base_from_member( MemberType& x ) + explicit constexpr __base_from_member__( MemberType& x ) noexcept; }; @@ -158,21 +153,21 @@ 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). +called `member` that the derived class can use for later base classes or +itself. If the appropriate features of C++11 are present, there will be a single constructor template. It implements ['perfect forwarding] to the best -constructor call of `member` (if any). The constructor template is marked +constructor call of `member` if any. The constructor template is marked both `constexpr` and `explicit`. The former will be ignored if the -corresponding inner constructor call (of `member`) does not have the marker. +corresponding inner constructor call of `member` does not have the marker. The latter binds the other way; always taking effect, even when the inner constructor call does not have the marker. The constructor template -propagates the `noexcept` status of the inner constructor call. (The +propagates the `noexcept` status of the inner constructor call. The constructor template has a trailing parameter with a default value that disables the template when its signature is too close to the signatures of the automatically-defined non-template copy- and/or move-constructors of -`base_from_member`.) +__base_from_member__. On earlier-standard compilers, there is a default constructor and several constructor member templates. These constructor templates can take as many @@ -195,150 +190,157 @@ 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.) This constant is ignored when C++11 features are present. -[endsect] -[section Usage] +[heading Basic Usage] With the starting example, the `fdoutbuf` sub-object needs to be -encapsulated in a base class that is inheirited before `std::ostream`. +encapsulated in a base class that is inherited before `__std_ostream__`. - #include +``` +#include - #include // for std::streambuf - #include // for std::ostream +#include // for std::streambuf +#include // for __std_ostream__ - class fdoutbuf - : public std::streambuf - { - public: - explicit fdoutbuf( int fd ); - //... - }; +class fdoutbuf + : public __std_streambuf__ +{ +public: + explicit fdoutbuf( int fd ); + //... +}; - class fdostream - : private boost::base_from_member - , public std::ostream - { - // Helper typedef's - typedef boost::base_from_member pbase_type; - typedef std::ostream base_type; +class fdostream + : private __boost_base_from_member__ + , public __std_ostream__ +{ + // Helper typedef's + typedef __boost_base_from_member__ pbase_type; + typedef __std_ostream__ base_type; - public: - explicit fdostream( int fd ) - : pbase_type( fd ), base_type( &member ){} - //... - }; +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 +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. -[endsect] -[section Example] +[heading Multiple Sub-Objects] 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 +``` +#include - #include /* for NULL */ +#include /* for NULL */ - struct an_int - { - int y; +struct an_int +{ + int y; - an_int( float yf ); - }; + an_int( float yf ); +}; - class switcher - { - public: - switcher(); - switcher( double, int * ); - //... - }; +class switcher +{ +public: + switcher(); + switcher( double, int * ); + //... +}; - class flow_regulator - { - public: - flow_regulator( switcher &, switcher & ); - //... - }; +class flow_regulator +{ +public: + flow_regulator( switcher &, switcher & ); + //... +}; - template < unsigned Size > - class fan - { - public: - explicit fan( switcher ); - //... - }; +template < unsigned Size > +class fan +{ +public: + explicit fan( switcher ); + //... +}; - class system - : private boost::base_from_member - , private boost::base_from_member - , private boost::base_from_member - , private boost::base_from_member - , protected flow_regulator - , public fan<6> - { - // Helper typedef's - typedef boost::base_from_member pbase0_type; - typedef boost::base_from_member pbase1_type; - typedef boost::base_from_member pbase2_type; - typedef boost::base_from_member pbase3_type; +class system + : private __boost_base_from_member__ + , private __boost_base_from_member__ + , private __boost_base_from_member__ + , private __boost_base_from_member__ + , protected flow_regulator + , public fan<6> +{ + // Helper typedef's + typedef __boost_base_from_member__ pbase0_type; + typedef __boost_base_from_member__ pbase1_type; + typedef __boost_base_from_member__ pbase2_type; + typedef __boost_base_from_member__ pbase3_type; - typedef flow_regulator base1_type; - typedef fan<6> base2_type; + typedef flow_regulator base1_type; + typedef fan<6> base2_type; - public: - system( double x ); - //... - }; +public: + system( double x ); + //... +}; - system::system( double x ) - : pbase0_type( 0.2 ) - , pbase1_type() - , pbase2_type( -16, &this->pbase0_type::member.y ) - , pbase3_type( x, static_cast(NULL) ) - , base1_type( pbase3_type::member, pbase1_type::member ) - , base2_type( pbase2_type::member ) - { - //... - } +system::system( double x ) + : pbase0_type( 0.2 ) + , pbase1_type() + , pbase2_type( -16, &this->pbase0_type::member.y ) + , pbase3_type( x, static_cast(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. +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__:: *`) +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++ (except `nullptr` from C++11) 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. (If C++11's `nullptr` is used, it still needs a -conversion if multiple pointer types can be accepted in a constructor call -but `std::nullptr_t` cannot.) +take either an integer or a pointer. -[endsect] +The last conversion is necessary for the compiler to call a constructor form + with the exact pointer type used in `switcher`'s constructor. (If C++11's + __nullptr__ is used, it still needs a conversion if multiple pointer types can + be accepted in a constructor call but `__std_nullptr_t__` cannot.) -[section Acknowledgments] +[heading Acknowledgments] + +Author: Walker, Daryle + +Copyright 2001, 2003, 2004, 2012 Daryle Walker * [@http://www.boost.org/people/ed_brey.htm Ed Brey] suggested some interface changes. @@ -353,10 +355,10 @@ the idiom of how to use a class member for initializing a base class. * Jonathan Turkanis supplied an implementation of generating the constructor templates that can be controlled and automated with macros. The -implementation uses the [@../../../preprocessor/index.html Preprocessor library]. +implementation uses the [@boost:/doc/html/preprocessor/index.html Preprocessor library]. * [@http://www.boost.org/people/daryle_walker.html">Daryle Walker] started the -library. Contributed the test file [@../../test/base_from_member_test.cpp +library. Contributed the test file [@../../../test/base_from_member_test.cpp base_from_member_test.cpp]. [endsect] diff --git a/doc/call_traits.qbk b/doc/call_traits.qbk new file mode 100644 index 0000000..60aa36a --- /dev/null +++ b/doc/call_traits.qbk @@ -0,0 +1,432 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / Distributed under 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) + /] + +[/===============] +[section Call Traits] +[/===============] + +[heading Introduction] + +All of the contents of [@../../../include/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 `typedef`s defined +as in the table below. The purpose of __call_traits__ is to ensure +that problems like [link sec:refs "references to references"] +never occur, and that parameters are passed in the most efficient +manner possible, as in the [link sec:examples 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__ cannot be used with array types, although it can still be +used to solve the reference to reference problem. + +[table __call_traits__ types + [[Existing practice] [__call_traits__ equivalent] [Description] [Notes]] + [ + [`T` + + (return by value) + ] + [ + __call_traits_T__`::value_type` + ] + [ + Defines a type that represents the "value" of type `T`. + + Use this for functions that return by value, or possibly for stored values of type `T`. + ] + [2] + ] + [ + [`T&` + + (return value) + ] + [ + __call_traits_T__`::reference` + ] + [ + Defines a type that represents a reference to type `T`. + + Use for functions that would normally return a `T&`. + ] + [1] + ] + [ + [`const T&` + + (return value) + ] + [ + __call_traits_T__`::const_reference` + ] + [ + Defines a type that represents a constant reference to type `T`. + + Use for functions that would normally return a `const T&`. + ] + [1] + ] + [ + [`const T&` + + (function parameter) + ] + [ + __call_traits_T__`::param_type` + ] + [ + Defines a type that represents the "best" way to pass a parameter of type `T` to a function. + ] + [1,3] + ] +] + +Notes: + +# If `T` is already reference type, then __call_traits__ is + defined such that [link sec:refs "references to references"] + do not occur (requires partial specialization). +# If `T` is an array type, then __call_traits__ defines `value_type` + as a "constant pointer to type" rather than an + "array of type" (requires partial specialization). + Note that if you are using `value_type` as a stored value + then this will result in storing a "constant pointer to + an array" rather than the array itself. This may or may + not be a good thing depending upon what you actually + need (in other words take care!). +# If `T` is a small built in type or a pointer, then `param_type` + is defined as `T const`, instead of `T const&`. This can + improve the ability of the compiler to optimize loops in + the body of the function if they depend upon the passed + parameter, the semantics of the passed parameter is + otherwise unchanged (requires partial specialization). + + +[heading Copy constructibility] + +The following table defines which __call_traits__ types can always +be copy-constructed from which other types: + +[table Which __call_traits__ types can always be copy-constructed from which other types + [[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]] + [[From `T`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]] + [[From `value_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]] + [[From `reference`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]] + [[From `const_reference`] [iff `T` is copy constructible] [No] [No] [Yes] [Yes]] + [[From `param_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]] +] + +If `T` is an assignable type the following assignments are possible: + +[table Which __call_traits__ types are assignable from which other types + [[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]] + [[From `T`] [Yes] [Yes] [-] [-] [-]] + [[From `value_type`] [Yes] [Yes] [-] [-] [-]] + [[From `reference`] [Yes] [Yes] [-] [-] [-]] + [[From `const_reference`] [Yes] [Yes] [-] [-] [-]] + [[From `param_type`] [Yes] [Yes] [-] [-] [-]] +] + +[#sec:examples] +[heading Examples] + +The following table shows the effect that __call_traits__ has on +various types. + +[table Examples of __call_traits__ types + [[] [__call_traits__::`value_type`] [__call_traits__::`reference`] [__call_traits__::`const_reference`] [__call_traits__::`param_type`] [Applies to:]] + [[From `my_class`] [`my_class`] [`my_class&`] [`const my_class&`] [`my_class const&`] [All user-defined types]] + [[From `int`] [`int`] [`int&`] [`const int&`] [`int const`] [All small built-in types]] + [[From `int*`] [`int*`] [`int*&`] [`int* const &`] [`int* const`] [All pointer types]] + [[From `int&`] [`int&`] [`int&`] [`const int&`] [`int&`] [All reference types]] + [[From `const int&`] [`const int&`] [`const int&`] [`const int&`] [`const int&`] [All constant reference types]] + [[From `int[3]`] [`const int*`] [`int(&)[3]`] [`const int(&)[3]`] [`const int* const`] [All array types]] + [[From `const int[3]`] [`const int*`] [`const int(&)[3]`] [`const int(&)[3]`] [`const int *const`] [All constant array types]] +] + +The table assumes the compiler supports partial +specialization: if it does not then all types behave in +the same way as the entry for "`my_class`", and +__call_traits__ can not be used with reference or array types. + +[heading Example 1:] + +The following class is a trivial class that stores some type `T` +by value (see the [@../../../test/call_traits_test.cpp `call_traits_test.cpp`] +file). The aim is to illustrate how each of the available +__call_traits__ `typedef`s may be used: + +``` +template +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__::param_type param_type; + typedef typename __boost_call_traits__::reference reference; + typedef typename __boost_call_traits__::const_reference const_reference; + typedef T value_type; + typedef typename __boost_call_traits__::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){} + +}; +``` + +[#sec:refs] +[heading Example 2 (the reference to reference problem):] + +Consider the definition of __std_binder1st__: + +``` +template +class binder1st : + public __std_unary_function__ +{ +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__::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. + +[#sec:example3] +[heading Example 3 (the `make_pair` problem):] + +If we pass the name of an array as one (or both) arguments to `__std_make_pair__`, +then template argument deduction deduces the passed parameter as +"const reference to array of `T`", this also applies to +string literals (which are really array literals). Consequently +instead of returning a pair of pointers, it tries to return a +pair of arrays, and since an array type is not copy-constructible +the code fails to compile. One solution is to explicitly cast the +arguments to __std_make_pair__ to pointers, but __call_traits__ provides a +better automatic solution that works safely even in generic code where the +cast might do the wrong thing: + +``` +template +__std_pair__< + typename __boost_call_traits__::value_type, + typename __boost_call_traits__::value_type> + make_pair(const T1& t1, const T2& t2) +{ + return __std_pair__< + typename __boost_call_traits__::value_type, + typename __boost_call_traits__::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 +__std_make_pair__ are not expressed in terms of __call_traits__: doing so +would prevent template argument deduction from functioning. + +[#sec:example4] +[heading Example 4 (optimising fill):] + +The __call_traits__ template will "optimize" the passing +of a small built-in type as a function parameter. This mainly has +an effect when the parameter is used within a loop body. + +In the following example (see [@boost:/doc/html/type_traits/examples/fill_example.cpp `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++ implementation is +used, but with the passed parameter "optimized" using +__call_traits__: + +``` +template +struct filler +{ + template + static void do_fill(I first, I last, typename __boost_call_traits__::param_type val) + { + while(first != last) + { + *first = val; + ++first; + } + } +}; + +template <> +struct filler +{ + template + static void do_fill(I first, I last, T val) + { + __std_memset__(first, val, last-first); + } +}; + +template +inline void fill(I first, I last, const T& val) +{ + enum { can_opt = boost::is_pointer::value + && boost::is_arithmetic::value + && (sizeof(T) == 1) }; + typedef filler filler_t; + filler_t::template do_fill(first, last, val); +} +``` + +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__. + +[heading Rationale] + +The following notes are intended to briefly describe the +rationale 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 [@https://en.cppreference.com/w/cpp/language/types fundamental +types], 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 [link sec:example4 Example 4]). In any case this should never +be any worse than existing practice. + +Pointers follow the same rationale as small built-in types. + +For reference types the rationale follows [link sec:refs 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 +struct A +{ + void foo(T t); +}; +``` + +In this case if we instantiate `A` then the declared type of +the parameter passed to member function `foo` is `int[2]`, but its +actual type is `const int*`. If we try to use the type `T` within the +function body, then there is a strong likelihood that our code will not compile: + +``` +template +void A::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 +struct A +{ + void foo(typename __call_traits__::value_type t); +}; + +template +void A::foo(typename __call_traits__::value_type t) +{ + typename __call_traits__::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 - +[link sec:example3 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 does not 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. + +[endsect] + + + + diff --git a/doc/compressed_pair.qbk b/doc/compressed_pair.qbk index eac4266..bdc8768 100644 --- a/doc/compressed_pair.qbk +++ b/doc/compressed_pair.qbk @@ -1,5 +1,6 @@ [/ Copyright 2000 Beman Dawes & John Maddock. + Copyright (c) 2021, Alan Freitas Distributed under the Boost Software License, Version 1.0. @@ -7,89 +8,77 @@ or copy at http://boost.org/LICENSE_1_0.txt ] -[article Compressed_Pair - [quickbook 1.5] - [authors [Cleary, Steve]] - [authors [Dawes, Beman]] - [authors [Hinnant, Howard]] - [authors [Maddock, John]] - [copyright 2000 Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock] - [license - Distributed under 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]) - ] -] +[section Compressed Pair] -[section Overview] +[heading Introduction] -All of the contents of `` are defined inside +All of the contents of [@../../../include/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. +The class __compressed_pair__ is very similar to __std_pair__. However, if either of +the template arguments are empty classes, then the +[@https://en.cppreference.com/w/cpp/language/ebo ['empty base-class optimisation]] +is applied to compress the size of the pair. -[endsect] +[heading Synopsis] -[section Synopsis] +```cpp +template +class __compressed_pair__ +{ +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename __call_traits__::param_type first_param_type; + typedef typename __call_traits__::param_type second_param_type; + typedef typename __call_traits__::reference first_reference; + typedef typename __call_traits__::reference second_reference; + typedef typename __call_traits__::const_reference first_const_reference; + typedef typename __call_traits__::const_reference second_const_reference; - template - class compressed_pair - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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() : 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&); - compressed_pair& operator=(const compressed_pair&); + first_reference first(); + first_const_reference first() const; - first_reference first(); - first_const_reference first() const; + second_reference second(); + second_const_reference second() const; - second_reference second(); - second_const_reference second() const; - - void swap(compressed_pair& y); - }; + 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 +__compressed_pair__ can be instantiated for reference and array types, +however in these cases the range of constructors that can be used is 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 +Note that if either member is a [@https://en.cppreference.com/w/cpp/named_req/PODType POD] +type, then that member is not zero-initialized by the __compressed_pair__ default constructor: +it is 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 +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. +[@boost:/doc/html/type_traits/index.html `boost::is_union`], or +if [@boost:/doc/html/type_traits/index.html `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. -[endsect] - -[section Acknowledgments] +[heading Acknowledgments] Based on contributions by Steve Cleary, Beman Dawes, Howard Hinnant and John Maddock. diff --git a/doc/declval.qbk b/doc/declval.qbk deleted file mode 100644 index 22ba11e..0000000 --- a/doc/declval.qbk +++ /dev/null @@ -1,114 +0,0 @@ -[/ - / Copyright (c) 2008 Howard Hinnant - / Copyright (c) 2009-2012 Vicente J. Botet Escriba - / - / Distributed under 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) - /] - -[article Declval - [quickbook 1.5] - [authors [Hinnant, Howard]] - [authors [Botet Escriba, Vicente J.]] - [copyright 2008 Howard Hinnant] - [copyright 2009-2012 Vicente J. Botet Escriba] - [license - Distributed under 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]) - ] -] - -[/===============] -[section Overview] -[/===============] - -The motivation for `declval` was introduced in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2958.html#Value N2958: -Moving Swap Forward]. Here follows a rewording of this chapter. - -With the provision of decltype, late-specified return types, and default template-arguments for function templates a -new generation of SFINAE patterns will emerge to at least partially compensate the lack of concepts on the C++0x timescale. -Using this technique, it is sometimes necessary to obtain an object of a known type in a non-using context, e.g. given the declaration - - template - T&& declval(); // not used - -as part of the function template declaration - - template - decltype(static_cast(declval())) convert(From&&); - -or as part of a class template definition - - template class result_of; - - template - struct result_of - { - typedef decltype(declval()(declval()...)) type; - }; - -The role of the function template declval() is a transformation of a type T into a value without using or evaluating this function. -The name is supposed to direct the reader's attention to the fact that the expression `declval()` is an lvalue if and only if -T is an lvalue-reference, otherwise an rvalue. To extend the domain of this function we can do a bit better by changing its declaration to - - template - typename std::add_rvalue_reference::type declval(); // not used - -which ensures that we can also use cv void as template parameter. The careful reader might have noticed that `declval()` -already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C++0x standard. - -The provision of a new library component that allows the production of values in unevaluated expressions is considered -important to realize constrained templates in C++0x where concepts are not available. -This extremely light-weight function is expected to be part of the daily tool-box of the C++0x programmer. - -[endsect] - - -[/=================] -[section:reference Reference ] -[/=================] - -`#include ` - - namespace boost { - - template - typename add_rvalue_reference::type declval() noexcept; // as unevaluated operand - - } // namespace boost - - -The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands. - - template - typename add_rvalue_reference::type declval(); - -[*Remarks:] If this function is used, the program is ill-formed. - -[*Remarks:] The template parameter T of declval may be an incomplete type. - -[*Example:] - - template - decltype(static_cast(declval())) convert(From&&); - -Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To. - -[endsect] - -[/===============] -[section History] -[/===============] - -[heading boost 1.50] - -Fixes: - -* [@http://svn.boost.org/trac/boost/ticket/6570 #6570] Adding noexcept to boost::declval. - -[endsect] - - - - diff --git a/doc/in_place_factory.qbk b/doc/in_place_factory.qbk new file mode 100644 index 0000000..f36cdab --- /dev/null +++ b/doc/in_place_factory.qbk @@ -0,0 +1,300 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / Distributed under 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) + /] + +[/===============] +[#sec:in_place_factory] +[section In-place Factory] +[/===============] + +[heading Introduction] + +Suppose we have a class + +``` +struct X +{ + X ( int, _std__string_ ) ; +}; +``` + +And a container for it which supports an empty state. That is, a container which can contain zero objects: + +``` +struct C +{ + C() : contained_(0) {} + ~C() { delete contained_ ; } + X* contained_ ; +}; +``` + +A container designed to support an empty state typically does not require the contained type to be +__DefaultConstructible__, but it typically requires it to be __CopyConstructible__ as a mechanism to +initialize the object to store: + +``` +struct C +{ + C() : contained_(0) {} + C ( X const& v ) : contained_ ( new X(v) ) {} + ~C() { delete contained_ ; } + X* contained_ ; +}; +``` + +There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction, +there must exist a previously constructed source object to copy from. This object is likely to be temporary and serve +no purpose besides being the source: + +``` +void foo() +{ + // Temporary object created. + C c( X(123,"hello") ) ; +} +``` + +A solution to this problem is to support direct construction of the contained +object right in the container's storage. + +In this scheme, the user supplies the arguments for the `X` constructor +directly to the container: + +``` +struct C +{ + C() : contained_(0) {} + C ( X const& v ) : contained_ ( new X(v) ) {} + C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {} + ~C() { delete contained_ ; } + X* contained_ ; +}; +``` + +``` +void foo() +{ + // Wrapped object constructed in-place + // No temporary created. + C c(123,"hello"); +} +``` + +Clearly, this solution does not scale well since the container must duplicate all the constructor overloads +from the contained type, or at least all those which are to be supported directly in the container. + +[heading Framework] + +This library proposes a framework to allow some containers to directly construct contained objects in-place without requiring +the entire set of constructor overloads from the contained type. It also allows the container to remove the __CopyConstructible__ +requirement from the contained type since objects can be directly constructed in-place without need of a copy. + +The only requirement on the container is that it must provide proper storage. That is, the container should be +correctly aligned and sized. Naturally, the container will typically support uninitialized storage to avoid the +in-place construction to override a fully-constructed object, as this would defeat the purpose of in-place construction. + +For this purpose, the framework provides two concepts called: InPlaceFactories and TypedInPlaceFactories. +Helpers to declare these classes are declared in [@../../../include/boost/utility/in_place_factory.hpp ``] +and [@../../../include/boost/utility/typed_in_place_factory.hpp ``]. + +Essentially, these classes hold a sequence of actual parameters and a method to construct an object in place using these parameters. +Each member of the family differs only in the number and type of the parameter list. The first family +takes the type of the object to construct directly in method provided for that +purpose, whereas the second family incorporates that type in the factory class +itself. From the container point of view, using the framework amounts to calling the +factory's method to contruct the object in place. From the user point of view, it amounts to creating +the right factory object to hold the parameters and pass it to the container. + +The following simplified example shows the basic idea. A complete example follows the formal specification of the framework: + +``` +struct C +{ + template + C ( InPlaceFactory const& aFactory ) + : + contained_ ( uninitialized_storage() ) + { + aFactory.template apply(contained_); + } + + ~C() + { + contained_ -> X::~X(); + delete[] contained_ ; + } + + char* uninitialized_storage() { return new char[sizeof(X)] ; } + + char* contained_ ; +}; + +void foo() +{ + C c( in_place(123,"hello") ) ; +} + +``` + +[heading Specification] + +The following is the first member of the family of `InPlaceFactory` classes, along with its corresponding helper template function. +The rest of the family varies only in the number and type of template and constructor parameters. + + +``` +namespace boost { + +struct __in_place_factory_base__ {}; + +template +class in_place_factory : public __in_place_factory_base__ +{ + public: + in_place_factory ( A0 const& a0 ) : m_a0(a0) {} + + template< class T > + void apply ( void* address ) const + { + new (address) T(m_a0); + } + + private: + A0 const& m_a0 ; +}; + +template +in_place_factory in_place ( A0 const& a0 ) +{ + return in_place_factory(a0); +} + +} +``` + +Similarly, the following is the first member of the family of `typed_in_place_factory` classes, along with its corresponding +helper template function. The rest of the family varies only in the number and type of template and constructor parameters. + +``` +namespace boost { + +struct __typed_in_place_factory_base__ {}; + +template +class typed_in_place_factory : public __typed_in_place_factory_base__ +{ + public: + typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {} + + void apply ( void* address ) const + { + new (address) T(m_a0); + } + + private: + A0 const& m_a0 ; +}; + +template +typed_in_place_factory in_place ( A0 const& a0 ) +{ + return typed_in_place_factory(a0); +} +} +``` + +As you can see, the `in_place_factory` and `typed_in_place_factory` template classes vary only in the way they specify +the target type: in the first family, the type is given as a template argument to the apply member function while in the +second it is given directly as part of the factory class. + +When the container holds a unique non-polymorphic type, such as the case of [@boost:/doc/html/optional/index.html Boost.Optional], +it knows the exact dynamic-type of the contained object and can pass it to the `apply()` method of a non-typed factory. +In this case, end users can use an `in_place_factory` instance which can be constructed without the type of the object to construct. + +However, if the container holds heterogeneous or polymorphic objects, such as the case of [@boost:/doc/html/variant/index.html Boost.Variant], +the dynamic-type of the object to be constructed must be known by the factory. In this case, end users must use a `typed_in_place_factory` +instead. + +[heading Container-side Usage] + +As shown in the introductory simplified example, the container class must contain methods that accept an instance of +these factories and pass the object's storage to the factory's apply method. + +However, the type of the factory class cannot be completely specified in the container class because that would +defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list +for the constructor of its contained object. + +The correct function overload must be based on the only distinctive and common +characteristic of all the classes in each family: the base class. + +Depending on the container class, you can use `enable_if` to generate the right overload, or use the following +dispatch technique, which is used in the [@boost:/doc/html/optional/index.html Boost.Optional] class: + + +``` +struct C +{ + C() : contained_(0) {} + C ( X const& v ) : contained_ ( new X(v) ) {} + + template + C ( Expr const& expr ) + : + contained_ ( uninitialized_storage() ) + { + construct(expr,&expr); + } + + ~C() { delete contained_ ; } + + template + void construct ( InPlaceFactory const& aFactory, boost::__in_place_factory_base__* ) + { + aFactory.template apply(contained_); + } + + template + void construct ( TypedInPlaceFactory const& aFactory, boost::__typed_in_place_factory_base__* ) + { + aFactory.apply(contained_); + } + + X* uninitialized_storage() { return static_cast(new char[sizeof(X)]) ; } + + X* contained_ ; +}; +``` + +[heading User-side Usage] + +End users pass to the container an instance of a factory object holding the actual parameters needed to construct the +contained object directly within the container. For this, the helper template function `in_place` is used. + +The call `in_place(a0,a1,a2,...,an)` constructs a (non-typed) `in_place_factory` instance with the given argument list. + +The call `in_place(a0,a1,a2,...,an)` constructs a `typed_in_place_factory` instance with the given argument list for the +type `T`. + +``` +void foo() +{ + C a( in_place(123, "hello") ) ; // in_place_factory passed + C b( in_place(456, "world") ) ; // typed_in_place_factory passed +} + +``` + +[heading Acknowledgments] + +Copyright Fernando Luis Cacciola Carballal, 2004 + +[endsect] + + + + diff --git a/doc/operators.qbk b/doc/operators.qbk new file mode 100644 index 0000000..9fcc4a7 --- /dev/null +++ b/doc/operators.qbk @@ -0,0 +1,1986 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / Distributed under 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) + /] + +[/===============] +[#sec:operators] +[section Operators] +[/===============] + +[heading Introduction] + +The header [@../../../include/boost/operators.hpp ``] supplies +several sets of class templates in `namespace boost`. These templates define +operators at namespace scope in terms of a minimal number of fundamental +operators provided by the class. + +[#sec:rationale] +[heading Rationale] + +Overloaded operators for class types typically occur in groups. If you +can write `x + y`, you probably also want to be able to write `x += y`. +If you can write `x < y,` you also want `x > y`, `x >= y,` and `x <= y`. + +Moreover, unless your class has really surprising behavior, some of these +related operators can be defined in terms of others (e.g. `x >= y` +is equivalent to `!(x < y)`). + +Replicating this boilerplate for multiple classes is both tedious and +error-prone. The [@../../../include/boost/operators.hpp ``] templates +help by generating operators for you at namespace scope based on other +operators you have defined in your class. + +If, for example, you declare a class like this: + +``` +class MyInt +: boost::__operators__ +{ + 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>`, `operator<=`, `operator>=`, and the binary `operator+`. + +[link sec:two_arg Two-argument forms] of the templates are also provided to allow interaction with other types. + +[#sec:semantics] +This is a ['Summary of Template Semantics]: + +# Each operator template completes the concept(s) it describes by defining overloaded operators for its target class. +# The name of an operator class template indicates the [link sec:concepts_note concept] that its target class will model. +# Usually, the target class uses an instantiation of the operator class template as a base class. Some operator templates support an + [link sec:explicit_instantiation alternate method]. +# The concept can be compound, i.e. it may represent a common combination of other, simpler concepts. +# Most operator templates require their target class to support operations related to the operators supplied by + the template. In accordance with widely accepted [@http://www.gotw.ca/gotw/004.htm coding style recommendations], the + target class is often required to supply the assignment counterpart operator of the concept's "main operator." + For example, the `addable` template requires `operator+=(T const&)` and in turn supplies `operator+(T const&, T const&)`. + +[#sec:concepts_note] + +['Note on the use of concepts]: The discussed concepts are not necessarily the standard library's +concepts, such as __CopyConstructible__, although some of them could +be; they are what we call ['concepts with a small 'c']. In +particular, they are different from the former ones in that they ['do +not] describe precise semantics of the operators they require to be +defined, except the requirements that (a) the semantics of the operators +grouped in one concept should be consistent (e.g. effects of +evaluating of `a += b` and `a = a + b` expressions should be the +same), and (b) that the return types of the operators should follow +semantics of return types of corresponding operators for built-in types +(e.g. `operator<` should return a type convertible to `bool`, and +`T::operator-=` should return type convertible to `T`). Such "loose" +requirements make `operators` library applicable to broader set of +target classes from different domains, i.e. eventually more useful. + +[#sec:example] +[heading Example] + +This example shows how some of the [link sec:arithmetic arithmetic +operator templates] can be used with a geometric point class +template. + +``` +template +class point // note: private inheritance is OK here! +: boost::addable< point // point + point +, boost::subtractable< point // point - point +, boost::dividable2< point, T // point / T +, boost::multipliable2< point, 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 +T length(const point p) +{ + return sqrt(p.x()*p.x() + p.y()*p.y()); +} + +const point right(0, 1); +const point up(1, 0); +const point pi_over_4 = up + right; +const point pi_over_4_normalized = pi_over_4 / length(pi_over_4); +``` + +[#sec:usage] +[heading Usage] + +[#sec:two_arg] +[h5 Two-Argument Template Forms] + +[#sec:two_arg_gen] + +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 [link sec:example 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 [link table:addable2 `addable`]. The comparison +templates [link table:less_than_comparable2 `less_than_comparable`], +[link table:equality_comparable2 `equality_comparable`], +[link table:equivalent2 `equivalent`], and +[link table:partially_ordered2 `partially_ordered`] 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 [link sec:chaining base class chaining] +technique. + +[#sec:mixed_arithmetics] + +['Mixed Arithmetics]: Another application of the + two-argument template forms is for mixed +arithmetics between a type `T` and a type `U` that +is convertible to `T`. In this case there are two ways where +the two-argument template forms are helpful: one is to provide the +respective signatures for operator overloading, the second is +performance. + +With respect to the operator overloading assume e.g. that +`U` is `int`, that `T` is an user-defined unlimited integer type, +and that `double operator-(double, const T&)` exists. + +If one wants to compute `int - T` and does not provide +`T operator-(int, const T&)`, the compiler will consider +`double operator-(double, const T&)` to be a better match +than `T operator-(const T&, const T&)`, which will probably +be different from the user's intention. + +To define a complete set of operator signatures, additional 'left' +forms of the two-argument template forms are provided +[link table:subtractable2_left `subtractable2_left`], +[link table:dividable2_left `dividable2_left`], and +[link table:modable2_left `modable2_left`] that +define the signatures for non-commutative operators where + `U` appears on the left hand side (`operator-(const U&, const T&)`, +`operator/(const U&, const T&)`, `operator%(const U&, const T&)`). + +With respect to the performance observe that when one uses the single +type binary operator for mixed type arithmetics, the type `U` +argument has to be converted to type `T`. In practice, +however, there are often more efficient implementations of, say +`T::operator-=(const U&)` that avoid unnecessary conversions +from `U` to `T`. + +The two-argument template forms of the arithmetic operator create +additional operator interfaces that use these more efficient implementations. +There is, however, no performance gain in the 'left' forms: they still need a +conversion from `U` to `T` and have an implementation equivalent to the code +that would be automatically created by the compiler if it considered the +single type binary operator to be the best match. + +[#sec:chaining] +[h5 Base Class Chaining and Object Size] + +Every operator class template, except the [link sec:ex_oprs arithmetic examples] +and the [link sec:iterator iterator helpers], has an additional, but optional, +template type parameter `B`. This parameter will be a publicly-derived base class of +the instantiated template. This means it must be a class type. It can be +used to avoid the bloating of object sizes that is commonly associated +with multiple-inheritance from several empty base classes. See the +[link sec:old_lib_note note for users of older versions] for more +details. + +To provide support for a group of operators, use the +`B` parameter to chain operator templates into a single-base +class hierarchy, demostrated in the [link sec:example usage example]. +The technique is also used by the composite operator templates to group +operator definitions. If a chain becomes too long for the compiler to +support, try replacing some of the operator templates with a single +grouped operator template that chains the old templates together; the +length limit only applies to the number of templates directly in the +chain, not those hidden in group templates. + +['Caveat]: to chain to a base class which is ['not] a Boost operator +template when using the [link sec:two_arg 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. + +[#sec:explicit_instantiation] +[h5 Separate Explicit Instantiation] + +On some compilers (e.g. Borland, GCC) even single-inheritance +seems to cause an increase in object size in some cases. If you are not +defining a class template, you may get better object-size performance by +avoiding derivation altogether, and instead explicitly instantiating the +operator template as follows: + +``` +class my_class // lose the inheritance... +{ + //... +}; + +// explicitly instantiate the operators I need. +template struct less_than_comparable; +template struct equality_comparable; +template struct incrementable; +template struct decrementable; +template struct addable; +template struct subtractable; +``` + + + +Note that some operator templates cannot use this workaround and must +be a base class of their primary operand type. Those templates define +operators which must be member functions, and the workaround needs the +operators to be independent `friend` functions. The relevant templates +are: + +* [link table:dereferenceable `dereferenceable<>`] +* [link table:indexable `indexable<>`] +* Any composite operator template that includes at least one of the above + +As Daniel Krugler pointed out, this technique violates 14.6.5/2 and is thus +non-portable. The reasoning is, that the operators injected by the instantiation +of e.g. `less_than_comparable` can not be found by ADL according to the +rules given by 3.4.2/2, since `my_class` is not an associated class of +`less_than_comparable`. Thus only use this technique if all else fails. + +[#sec:portability] +[h5 Requirement Portability] + +Many compilers (e.g. MSVC 6.3, GCC 2.95.2) will not enforce the +requirements in the operator template tables unless the operations which +depend on them are actually used. This is not standard-conforming +behavior. In particular, although it would be convenient to derive all +your classes which need binary operators from the [link table:operators1 `operators<>`] +and [link table:operators2 `operators2<>`] templates, regardless of +whether they implement all the requirements of those templates, this +shortcut is not portable. Even if this currently works with your +compiler, it may not work later. + +[#sec:arithmetic] +[heading Arithmetic Operators] + +The arithmetic operator templates ease the task of creating a custom +numeric type. Given a core set of operators, the templates add related +operators to the numeric class. These operations are like the ones the +standard arithmetic types have, and may include comparisons, adding, +incrementing, logical and bitwise manipulations, etc. Further, +since most numeric types need more than one of these operators, some +templates are provided to combine several of the basic operator templates +in one declaration. + +The requirements for the types used to instantiate the simple operator +templates are specified in terms of expressions which must be valid and +the expression's return type. The composite operator templates only list +what other templates they use. The supplied operations and requirements +of the composite operator templates can be inferred from the operations +and requirements of the listed components. + +[#sec:smpl_oprs] +[h5 Simple Arithmetic Operators] + +These templates are "simple" since they provide operators based on a +single operation the base type has to provide. They have an additional +optional template parameter `B`, which is not shown, for the +[link sec:chaining base class chaining] technique. + +The primary operand type `T` needs to be of class type, +built-in types are not supported. + +[table Notation + [[Key] [Description]] + [[`T`] [primary operand type]] + [[`t,t1`] [values of type `T`]] + [[`U`] [alternate operand type]] + [[`u`] [value of type `U`]] +] + +[table Simple Arithmetic Operator Template Classes + [[Template] [Supplied Operations] [Requirements] [Propagates constexpr]] + [ + [ + [#table:less_than_comparable1] `less_than_comparable` + + __less_than_comparable1__`` + ] + + [ + `bool operator>(const T&, const T&)` + + `bool operator<=(const T&, const T&)` + + `bool operator>=(const T&, const T&)` + ] + + [ + `t < t1`. + + Return convertible to `bool`. See the [link sec:ordering Ordering Note] + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:less_than_comparable2]`less_than_comparable` + + __less_than_comparable2__`` + ] + + [ + `bool operator<=(const T&, const U&)` + + `bool operator>=(const T&, const U&)` + + `bool operator>(const U&, const T&)` + + `bool operator<(const U&, const T&)` + + `bool operator<=(const U&, const T&)` + + `bool operator>=(const U&, const T&)` + ] + + [ + `t < u`. `t > u`. + + Returns convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:equality_comparable1]`equality_comparable` + + __equality_comparable1__`` + ] + + [ + `bool operator!=(const T&, const T&)` + ] + + [ + `t == t1`. + + Return convertible to `bool`. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:equality_comparable2]`equality_comparable` + + __equality_comparable2__`` + ] + + [ + `bool operator==(const U&, const T&)` + + `bool operator!=(const U&, const T&)` + + `bool operator!=(const T&, const U&)` + ] + + [ + `t == u`. + + Return convertible to `bool`. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:addable1]`addable` + + `addable1` + ] + + [ + `T operator+(const T&, const T&)` + ] + + [ + `T temp(t); temp += t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:addable2]`addable` + + `addable2` + ] + + [ + `T operator+(const T&, const U&)` + + `T operator+(const U&, const T& )` + ] + + [ + `T temp(t); temp += u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:subtractable1]`subtractable` + + `subtractable1` + ] + + [ + `T operator-(const T&, const T&)` + ] + + [ + `T temp(t); temp -= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:subtractable2]`subtractable` + + `subtractable2` + ] + + [ + `T operator-(const T&, const U&)` + ] + + [ + `T temp(t); temp -= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:subtractable2_left]`subtractable2_left` + ] + + [ + `T operator-(const U&, const T&)` + ] + + [ + `T temp(u); temp -= t`. + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:multipliable1]`multipliable` + + `multipliable1` + ] + + [ + `T operator*(const T&, const T&)` + ] + + [ + `T temp(t); temp *= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:multipliable2]`multipliable` + + `multipliable2` + ] + + [ + `T operator*(const T&, const U&)` + + `T operator*(const U&, const T&)` + ] + + [ + `T temp(t); temp *= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:dividable1]`dividable` + + `dividable1` + ] + + [ + `T operator/(const T&, const T&)` + ] + + [ + `T temp(t); temp /= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:dividable2]`dividable` + + `dividable2` + ] + + [ + `T operator/(const T&, const U&)` + ] + + [ + `T temp(t); temp /= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:dividable2_left]`dividable2_left` + ] + + [ + `T operator/(const U&, const T&)` + ] + + [ + `T temp(u); temp /= t`. + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:modable1]`modable` + + `modable1` + ] + + [ + `T operator%(const T&, const T&)` + ] + + [ + `T temp(t); temp %= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:modable2]`modable` + + `modable2` + ] + + [ + `T operator%(const T&, const U&)` + ] + + [ + `T temp(t); temp %= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:modable2_left]`modable2_left` + ] + + [ + `T operator%(const U&, const T&)` + ] + + [ + `T temp(u); temp %= t`. + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:orable1]`orable` + + `orable1` + ] + + [ + `T operator|(const T&, const T&)` + ] + + [ + `T temp(t); temp |= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:orable2]`orable` + + `orable2` + ] + + [ + `T operator|(const T&, const U&)` + + `T operator|(const U&, const T&)` + ] + + [ + `T temp(t); temp |= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:andable1]`andable` + + `andable1` + ] + + [ + `T operator&(const T&, const T&)` + ] + + [ + `T temp(t); temp &= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:andable2]`andable` + + `andable2` + ] + + [ + `T operator&(const T&, const U&)` + + `T operator&(const U&, const T&)` + ] + + [ + `T temp(t); temp &= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:xorable1]`xorable` + + `xorable1` + ] + + [ + `T operator^(const T&, const T&)` + ] + + [ + `T temp(t); temp ^= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:xorable2]`xorable` + + `xorable2` + ] + + [ + `T operator^(const T&, const U&)` + + `T operator^(const U&, const T&)` + ] + + [ + `T temp(t); temp ^= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:incrementable]`incrementable` + ] + + [ + `T operator++(T&, int)` + ] + + [ + `T temp(t); ++t` + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:decrementable]`decrementable` + ] + + [ + `T operator--(T&, int)` + ] + + [ + `T temp(t); --t;` + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:left_shiftable1]`left_shiftable` + + `left_shiftable1` + ] + + [ + `T operator<<(const T&, const T&)` + ] + + [ + `T temp(t); temp <<= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:left_shiftable2]`left_shiftable` + + `left_shiftable2` + ] + + [ + `T operator<<(const T&, const U&)` + ] + + [ + `T temp(t); temp <<= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:right_shiftable1]`right_shiftable` + + `right_shiftable1` + ] + + [ + `T operator>>(const T&, const T&)` + ] + + [ + `T temp(t); temp >>= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:right_shiftable2]`right_shiftable` + + `right_shiftable2` + ] + + [ + `T operator>>(const T&, const U&)` + ] + + [ + `T temp(t); temp >>= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:equivalent1]`equivalent` + + __equivalent1__`` + ] + + [ + `bool operator==(const T&, const T&)` + ] + + [ + `t < t1`. + + Return convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:equivalent2]`equivalent` + + __equivalent2__`` + ] + + [ + `bool operator==(const T&, const U&)` + ] + + [ + `t < u`. `t > u`. + + Returns convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:partially_ordered1]`partially_ordered` + + __partially_ordered1__`` + ] + + [ + `bool operator>(const T&, const T&)` + + `bool operator<=(const T&, const T&)` + + `bool operator>=(const T&, const T&)` + ] + + [ + `t < t1`. `t == t1`. + + Returns convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:partially_ordered2]`partially_ordered` + + __partially_ordered2__`` + ] + + [ + `bool operator<=(const T&, const U&)` + + `bool operator>=(const T&, const U&)` + + `bool operator>(const U&, const T&)` + + `bool operator<(const U&, const T&)` + + `bool operator<=(const U&, const T&)` + + `bool operator>=(const U&, const T&)` + ] + + [ + `t < u`. `t > u`. `t == u`. + + Returns convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] +] + +[#sec:ordering] +['Ordering Note]: The [link table:less_than_comparable1 `less_than_comparable`] and +[link table:partially_ordered1 `partially_ordered`] templates provide the same set +of operations. However, the workings of [link table:less_than_comparable1 `less_than_comparable`] assume +that all values of type `T` can be placed in a total order. If +that is not true (e.g. Not-a-Number values in IEEE floating point +arithmetic), then [link table:partially_ordered1 `partially_ordered`] should be +used. The [link table:partially_ordered1 `partially_ordered`] template can +be used for a totally-ordered type, but it is not as efficient as +[link table:less_than_comparable1 `less_than_comparable`]. This +rule also applies for [link table:less_than_comparable2 `less_than_comparable`] and +[link table:partially_ordered2 `partially_ordered`] with respect to the ordering +of all `T` and `U` values, and for both versions of +[link table:equivalent1 `equivalent<>`]. The solution for +[link table:equivalent1 `equivalent<>`] is to write a custom +`operator==` for the target class. + +[#sec:symmetry] +['Symmetry Note]: Before talking about symmetry, we need to talk about optimizations to +understand the reasons for the different implementation styles of +operators. Let's have a look at `operator+` for a class +`T` as an example: + +``` +T operator+( const T& lhs, const T& rhs ) +{ + return T( lhs ) += rhs; +} +``` + +This would be a normal implementation of `operator+`, but it +is not an efficient one. An unnamed local copy of `lhs` is +created, `operator+=` is called on it and it is copied to the +function return value (which is another unnamed object of type +`T`). The standard doesn't generally allow the intermediate +object to be optimized away: + +["3.7.2/2: Automatic storage duration: If a named automatic object has initialization or a destructor with +side effects, it shall not be destroyed before the end of its block, +nor shall it be eliminated as an optimization even if it appears to be +unused, except that a class object or its copy may be eliminated as +specified in 12.8.] + +The reference to 12.8 is important for us: + +["12.8/15: Copying class objects: (...) For a function with a class return type, if the expression in the +return statement is the name of a local object, and the cv-unqualified +type of the local object is the same as the function return type, an +implementation is permitted to omit creating the temporary object to +hold the function return value, even if the class copy constructor or +destructor has side effects.] + +This optimization is known as the named return value optimization (NRVO), +which leads us to the following implementation for `operator+`: + +``` +T operator+( const T& lhs, const T& rhs ) +{ + T nrv( lhs ); + nrv += rhs; + return nrv; +} +``` + +Given this implementation, the compiler is allowed to remove the +intermediate object. Sadly, not all compilers implement the NRVO, some +even implement it in an incorrect way which makes it useless here. +Without the NRVO, the NRVO-friendly code is no worse than the original +code showed above, but there is another possible implementation, which +has some very special properties: + +``` +T operator+( T lhs, const T& rhs ) +{ + return lhs += rhs; +} +``` + +The difference to the first implementation is that `lhs` is +not taken as a constant reference used to create a copy; instead, +`lhs` is a by-value parameter, thus it is already the copy +needed. This allows another optimization (12.2/2) for some cases. + +Consider `a + b + c` where the result of `a + b` is not copied when +used as `lhs` when adding `c`. This is more efficient than the original +code, but not as efficient as a compiler using the NRVO. For most people, +it is still preferable for compilers that don't implement the NRVO, but +the `operator+` now has a different function signature. Also, +the number of objects created differs for `(a + b ) + c` and `a + ( b + c )`. + +Most probably, this won't be a problem for you, but if your code relies on the function +signature or a strict symmetric behaviour, you should set +`BOOST_FORCE_SYMMETRIC_OPERATORS` in your user-config. This +will force the NRVO-friendly implementation to be used even for compilers +that do not implement the NRVO. + +[#sec:grpd_oprs] +[h5 Grouped Arithmetic Operators] + +The following templates provide common groups of related operations. +For example, since a type which is addable is usually also subtractable, +the [link table:additive1 `additive`] template provides the +combined operators of both. The grouped operator templates have an +additional optional template parameter `B`, which is not +shown, for the [link sec:chaining base class chaining] technique. + +[table Notation + [[Key] [Description]] + [[`T`] [primary operand type]] + [[`U`] [alternate operand type]] +] + +[table Grouped Arithmetic Operator Template Classes + [ + [Template] + + [Component Operator Templates] + ] + [ + [ + [#table:totally_ordered1] `totally_ordered` + + __totally_ordered1__`` + ] + [ + [link table:less_than_comparable1 `less_than_comparable`] + + [link table:equality_comparable1 `equality_comparable`] + ] + ] + [ + [ + [#table:totally_ordered2]`totally_ordered` + + __totally_ordered2__`` + ] + [ + [link table:less_than_comparable2 `less_than_comparable`] + + [link table:equality_comparable2 `equality_comparable`] + ] + ] + [ + [ + [#table:additive1]`additive` + + __additive1__`` + ] + [ + [link table:addable1 `addable`] + + [link table:subtractable1 `subtractable`] + ] + ] + [ + [ + [#table:additive2]`additive` + + __additive2__`` + ] + [ + [link table:addable2 `addable`] + + [link table:subtractable2 `subtractable`] + ] + ] + [ + [ + [#table:multiplicative1] `multiplicative` + + __multiplicative1__`` + ] + [ + [link table:multipliable1 `multipliable`] + + [link table:dividable1 `dividable`] + ] + ] + [ + [ + [#table:multiplicative2]`multiplicative` + + __multiplicative2__`` + ] + [ + [link table:multipliable2 `multipliable`] + + [link table:dividable2 `dividable`] + ] + ] + [ + [ + [#table:integer_multiplicative1] `integer_multiplicative` + + __integer_multiplicative1__`` + ] + [ + [link table:multiplicative1 `multiplicative`] + + [link table:modable1 `modable`] + ] + ] + [ + [ + [#table:integer_multiplicative2] `integer_multiplicative` + + __integer_multiplicative2__`` + ] + [ + [link table:multiplicative2 `multiplicative`] + + [link table:modable2 `modable`] + ] + ] + [ + [ + [#table:arithmetic1]`arithmetic` + + __arithmetic1__`` + ] + [ + [link table:additive1 `additive`] + + [link table:multiplicative1 `multiplicative`] + ] + ] + [ + [ + [#table:arithmetic2]`arithmetic` + + __arithmetic2__`` + ] + [ + [link table:additive2 `additive`] + + [link table:multiplicative2 `multiplicative`] + ] + ] + [ + [ + [#table:integer_arithmetic1] `integer_arithmetic` + + __integer_arithmetic1__`` + ] + [ + [link table:additive1 `additive`] + + [link table:integer_multiplicative1 `integer_multiplicative`] + ] + ] + [ + [ + [#table:integer_arithmetic2]`integer_arithmetic` + + __integer_arithmetic2__`` + ] + [ + [link table:additive2 `additive`] + + [link table:integer_multiplicative2 `integer_multiplicative`] + ] + ] + [ + [ + [#table:bitwise1]`bitwise` + + __bitwise1__`` + ] + [ + [link table:xorable1 `xorable`] + + [link table:andable1 `andable`] + + [link table:orable1 `orable`] + ] + ] + [ + [ + [#table:bitwise2]`bitwise` + + __bitwise2__`` + ] + [ + [link table:xorable2 `xorable`] + + [link table:andable2 `andable`] + + [link table:orable2 `orable`] + ] + ] + [ + [ + [#table:unit_steppable] `unit_steppable` + ] + [ + [link table:incrementable `incrementable`] + + [link table:decrementable `decrementable`] + ] + ] + [ + [ + [#table:shiftable1]`shiftable` + + __shiftable1__`` + ] + [ + [link table:left_shiftable1 `left_shiftable`] + + [link table:right_shiftable1 `right_shiftable`] + ] + ] + [ + [ + [#table:shiftable2]`shiftable` + + __shiftable2__`` + ] + [ + [link table:left_shiftable2 `left_shiftable`] + + [link table:right_shiftable2 `right_shiftable`] + ] + ] + [ + [ + [#table:ring_operators1] `ring_operators` + + __ring_operators1__`` + ] + [ + [link table:additive1 `additive`] + + [link table:multipliable1 `multipliable`] + ] + ] + [ + [ + [#table:ring_operators2]`ring_operators` + + __ring_operators2__`` + ] + [ + [link table:additive2 `additive`] + + [link table:subtractable2_left `subtractable2_left`] + + [link table:multipliable2 `multipliable`] + ] + ] + [ + [ + [#table:ordered_ring_operators1] `ordered_ring_operators` + + __ordered_ring_operators1__`` + ] + [ + [link table:ring_operators1 `ring_operators`] + + [link table:totally_ordered1 `totally_ordered`] + ] + ] + [ + [ + [#table:ordered_ring_operators2] `ordered_ring_operators` + + __ordered_ring_operators2__`` + ] + [ + [link table:ring_operators2 `ring_operators`] + + [link table:totally_ordered2 `totally_ordered`] + ] + ] + [ + [ + [#table:field_operators1]`field_operators` + + __field_operators1__`` + ] + [ + [link table:ring_operators1 `ring_operators`] + + [link table:dividable1 `dividable`] + ] + ] + [ + [ + [#table:field_operators2]`field_operators` + + __field_operators2__`` + ] + [ + [link table:ring_operators2 `ring_operators`] + + [link table:dividable2 `dividable`] + + [link table:dividable2_left `dividable2_left`] + ] + ] + [ + [ + [#table:ordered_field_operators1]`ordered_field_operators` + + __ordered_field_operators1__`` + ] + [ + [link table:field_operators1 `field_operators`] + + [link table:totally_ordered1 `totally_ordered`] + ] + ] + [ + [ + [#table:ordered_field_operators2]`ordered_field_operators` + + __ordered_field_operators2__`` + ] + [ + [link table:field_operators2 `field_operators`] + + [link table:totally_ordered2 `totally_ordered`] + ] + ] + [ + [ + [#table:euclidean_ring_operators1]`euclidean_ring_operators` + + __euclidean_ring_operators1__`` + ] + [ + [link table:ring_operators1 `ring_operators`] + + [link table:dividable1 `dividable`] + + [link table:modable1 `modable`] + ] + ] + [ + [ + [#table:euclidean_ring_operators2] `euclidean_ring_operators` + + __euclidean_ring_operators2__`` + ] + [ + [link table:ring_operators2 `ring_operators`] + + [link table:dividable2 `dividable`] + + [link table:dividable2_left `dividable2_left`] + + [link table:modable2 `modable`] + + [link table:modable2_left `modable2_left`] + ] + ] + [ + [ + [#table:ordered_euclidean_ring_operators1] `ordered_euclidean_ring_operators` + + __ordered_euclidean_ring_operators1__`` + ] + [ + [link table:euclidean_ring_operators1 `euclidean_ring_operators`] + + [link table:totally_ordered1 `totally_ordered`] + ] + ] + [ + [ + [#table:ordered_euclidean_ring_operators2]`ordered_euclidean_ring_operators` + + __ordered_euclidean_ring_operators2__`` + ] + [ + [link table:euclidean_ring_operators2 `euclidean_ring_operators`] + + [link table:totally_ordered2 `totally_ordered`] + ] + ] +] + +['Spelling: euclidean vs. euclidian]: Older versions of the +Boost.Operators library used "`euclidian`", but it was pointed out that +"`euclidean`" is the more common spelling. To be compatible with older +version, the library now supports both spellings. + +[#sec:ex_oprs] +[h5 Example Templates] + +The arithmetic operator class templates [link table:operators1 `operators<>`] and +[link table:operators2 `operators2<>`] are examples of non-extensible operator +grouping classes. These legacy class templates, from previous versions +of the header, cannot be used for [link sec:chaining base class chaining]. + +[table Notation + [[Key] [Description]] + [[`T`] [primary operand type]] + [[`U`] [alternate operand type]] +] + +[table Final Arithmetic Operator Template Classes + [ + [Template] + + [Component Operator Templates] + ] + [ + [ + [#table:operators1]__operators__`` + ] + [ + [link table:totally_ordered1 `totally_ordered`] + + [link table:integer_arithmetic1 `integer_arithmetic`] + + [link table:bitwise1 `bitwise`] + + [link table:unit_steppable `unit_steppable`] + ] + ] + [ + [ + [#table:operators2]__operators__`` + + __operators2__`` + ] + [ + [link table:totally_ordered2 `totally_ordered`] + + [link table:integer_arithmetic2 `integer_arithmetic`] + + [link table:bitwise2 `bitwise`] + ] + ] +] + +[#sec:a_demo] +['Arithmetic Operators Demonstration and Test Program]: The +[@../../../test/operators_test.cpp `operators_test.cpp`] +program demonstrates the use of the arithmetic operator templates, and +can also be used to verify correct operation. Check the compiler status +report for the test results with selected platforms. + +[#sec:deref] +[heading Dereference Operators and Iterator Helpers] + +The [link sec:iterator 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 [link sec:dereference dereference operators] were motivated by +the [link sec:iterator 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[]`. + +The requirements for the types used to instantiate the dereference +operators are specified in terms of expressions which must be valid and +their return type. The composite operator templates list their component +templates, which the instantiating type must support, and possibly other +requirements. + +[#sec:dereference] +[h5 Dereference Operators] + +All the dereference operator templates in this table accept an +optional template parameter (not shown) to be used for +[link sec:chaining base class chaining]. + +[table Notation + [[Key] [Description]] + [[`T`] [operand type]] + [[`D`] [`difference_type`]] + [[`i`] [object of type `T` (an iterator)]] + [[`P`] [`pointer` type]] + [[`R`] [`reference` type]] + [[`n`] [object of type `D` (an index)]] +] + +[table Dereference Operator Template Classes + [ + [Template] + + [Supplied Operations] + + [Requirements] + ] + [ + [ + [#table:dereferenceable]__dereferenceable__`` + ] + [ + `P operator->() const` + ] + [ + `*i`. Address of the returned value convertible to `P`. + ] + ] + [ + [ + [#table:indexable]__indexable__`` + ] + [ + `R operator[](D n) const` + ] + [ + `*(i + n)`. Return of type `R`. + ] + ] +] + +[#sec:grpd_iter_oprs] +[h5 Grouped Iterator Operators] + +There are five iterator operator class templates, each for a different +category of iterator. The following table shows the operator groups for +any category that a custom iterator could define. These class templates +have an additional optional template parameter `B`, which is +not shown, to support [link sec:chaining base class chaining]. + +[table Notation + [[Key] [Description]] + [[`T`] [operand type]] + [[`D`] [`difference_type`]] + [[`V`] [`value_type`]] + [[`P`] [`pointer` type]] + [[`R`] [`reference` type]] +] + +[table Iterator Operator Class Templates + [ + [Template] + + [Component Operator Templates] + ] + [ + [ + [#table:input_iteratable]__input_iteratable__`` + ] + [ + [link table:equality_comparable1 `equality_comparable`] + + [link table:incrementable `incrementable`] + + [link table:dereferenceable `dereferenceable`] + ] + ] + [ + [ + [#table:output_iteratable]__output_iteratable__`` + ] + [ + [link table:incrementable `incrementable`] + ] + ] + [ + [ + [#table:forward_iteratable]__forward_iteratable__`` + ] + [ + [link table:input_iteratable `input_iteratable`] + ] + ] + [ + [ + [#table:bidirectional_iteratable] __bidirectional_iteratable__`` + ] + [ + [link table:forward_iteratable `forward_iteratable`] + + [link table:decrementable `decrementable`] + ] + ] + [ + [ + [#table:random_access_iteratable] __random_access_iteratable__`` + ] + [ + [link table:bidirectional_iteratable `bidirectional_iteratable`] + + [link table:totally_ordered1 `totally_ordered`] + + [link table:additive2 `additive`] + + [link table:indexable `indexable`] + ] + ] +] + +[#sec:iterator] +[h5 Iterator Helpers] + +There are also five iterator helper class templates, each +corresponding to a different iterator category. These classes cannot be +used for [link sec:chaining base class chaining]. The following +summaries show that these class templates supply both the iterator +operators from the [link sec:grpd_iter_oprs iterator operator class +templates] and the iterator `typedef`s required by the C++ standard, +such as `iterator_category` and `value_type`. + +[table Notation + [[Key] [Description]] + [[`T`] [operand type]] + [[`D`] [`difference_type`]] + [[`V`] [`value_type`]] + [[`P`] [`pointer` type]] + [[`R`] [`reference` type]] + [[`x1`, `x2`] [objects of type `T`]] +] + +[table Helper Class Templates + [ + [Template] + + [Operations and Requirements] + ] + [ + [ + [#table:input_iterator_helper]__input_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:input_iteratable `input_iteratable`] + ] + ] + [ + [ + [#table:output_iterator_helper]__output_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:output_iteratable `output_iteratable`] + + See also \[[link note:1 1]\], \[[link note:2 2]\]. + ] + ] + [ + [ + [#table:forward_iterator_helper] __forward_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:forward_iteratable `forward_iteratable`] + ] + ] + [ + [ + [#table:bidirectional_iterator_helper] __bidirectional_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:bidirectional_iteratable `bidirectional_iteratable`] + ] + ] + [ + [ + [#table:random_access_iterator_helper]__random_access_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:random_access_iteratable `random_access_iteratable`] + + To satisfy __RandomAccessIterator__, `x1 - x2` with return convertible to `D` is also required. + ] + ] +] + +[#sec:iterator_helpers_notes] + +['Iterator Helper Notes]: + +# [#note:1] Unlike other iterator helpers templates, __output_iterator_helper__ takes only one template parameter - +the type of its target class. Although to some it might seem like an unnecessary restriction, the standard requires +`difference_type` and `value_type` of any output iterator to be `void` (24.3.1 [lib.iterator.traits]), and +__output_iterator_helper__ template respects this requirement. Also, output iterators in the standard have void `pointer` and +`reference` types, so the __output_iterator_helper__ does the same. +# [#note:2] As self-proxying is the easiest and most common way to implement output iterators (see, +for example, insert [24.4.2] and stream iterators [24.5] in the standard library), +__output_iterator_helper__ supports the idiom by defining `operator*` and `operator++` member functions which +just return a non-const reference to the iterator itself. Support for self-proxying allows us, in many cases, +to reduce the task of writing an output iterator to writing just two member functions - an appropriate +constructor and a copy-assignment operator. For example, here is a possible implementation of +[@boost:/doc/html/iterator/doc/function_output_iterator.html `boost::function_output_iterator`] adaptor: + +``` +template +struct function_output_iterator + : boost::__output_iterator_helper__< function_output_iterator > +{ + explicit function_output_iterator(UnaryFunction const& f = UnaryFunction()) + : func(f) {} + + template + function_output_iterator& operator=(T const& value) + { + this->func(value); + return *this; + } + +private: + UnaryFunction func; +}; +``` + +Note that support for self-proxying does not prevent you from using +__output_iterator_helper__ to ease any other, different kind of +output iterator's implementation. If +__output_iterator_helper__'s target type provides its own +definition of `operator*` or/and `operator++`, then +these operators will get used and the ones supplied by +__output_iterator_helper__ will never be instantiated. + +[#sec:i_demo] +[h5 Iterator Demonstration and Test Program] + +The [@../../../test/iterators_test.cpp `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 +struct test_iter + : public boost::__random_access_iterator_helper__< + test_iter, T, __std_ptrdiff_t__, P, R + > +{ + typedef test_iter self; + typedef R Reference; + typedef __std_ptrdiff_t__ Distance; + +public: + explicit test_iter(T* i =0); + test_iter(const self& x); + self& operator=(const self& x); + Reference operator*() const; + self& operator++(); + self& operator--(); + self& operator+=(Distance n); + self& operator-=(Distance n); + bool operator==(const self& x) const; + bool operator<(const self& x) const; + friend Distance operator-(const self& x, const self& y); +}; +``` + +Check the [@http://www.boost.org/development/testing.html compiler status report] for the +test results with selected platforms. + +[#sec:old_lib_note] +[heading Note for Users of Older Versions] + +The [link sec:chaining 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 are not ['forced] to change any existing code, +but the old usage is deprecated. + +Though it was arguably simpler and more intuitive than using +[link sec:chaining 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` from the [link sec:example 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] paragraph 5 of the standard). + +But the language definition also does not ['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 are 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 to remain backward-compatible. + +[#sec:contributors] +[heading Acknowledgments] + +* [@http://www.boost.org/people/dave_abrahams.htm Dave Abrahams]: + Started the library and contributed the arithmetic operators in + [@../../../include/boost/operators.hpp `boost/operators.hpp`]. + +* [@http://www.boost.org/people/jeremy_siek.htm Jeremy Siek]: + Contributed the [link sec:deref dereference operators and iterator + helpers] in [@../../../include/boost/operators.hpp boost/operators.hpp]. + Also contributed [@../../../test/iterators_test.cpp iterators_test.cpp]. + +* [@http://www.boost.org/people/aleksey_gurtovoy.htm Aleksey Gurtovoy]: + Contributed the code to support [link sec:chaining base class + chaining] while remaining backward-compatible with old versions of + the library. + +* [@http://www.boost.org/people/beman_dawes.html Beman Dawes]: + Contributed [@../../../test/operators_test.cpp `operators_test.cpp`]. + +* [@http://www.boost.org/people/daryle_walker.html Daryle Walker]: + Contributed classes for the shift operators, equivalence, partial + ordering, and arithmetic conversions. Added the grouped operator + classes. Added helper classes for input and output iterators. + +* Helmut Zeisel: Contributed the 'left' operators and added some grouped operator + classes. + +* Daniel Frey: Contributed the NRVO-friendly and symmetric implementation of + arithmetic operators. + +[endsect] diff --git a/doc/result_of.qbk b/doc/result_of.qbk new file mode 100644 index 0000000..f65232d --- /dev/null +++ b/doc/result_of.qbk @@ -0,0 +1,407 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / Distributed under 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) + /] + +[/===============] +[section Result of] +[/===============] + +[heading Introduction] + +The class template __result_of__ helps determine the type of a +call expression. For example, given an lvalue `f` of type `F` +and lvalues `t1`,`t2`, ..., `tN` of types `T1`, `T2`, ..., `TN`, +respectively, the type __result_of__`::type` defines +the result type of the expression `f(t1, t2, ...,tN)`. + +This implementation permits the type `F` to be a function pointer, +function reference, member function pointer, or class type. By default, +N may be any value between 0 and 16. To change the upper limit, define +the macro `BOOST_RESULT_OF_NUM_ARGS` to the maximum value for N. Class +template __result_of__ resides in the header +[@../../../include/boost/utility/result_of.hpp ``]. + +If your compiler's support for __decltype__ is adequate, __result_of__ +automatically uses it to deduce the type of the call expression, in +which case __result_of__`::type` names the type +__decltype__`(boost::declval()(boost::declval(), +boost::declval(), ..., boost::declval()))`, as in the +following example. + +``` +struct functor { + template + T operator()(T x) + { + return x; + } +}; + +typedef __boost_result_of__::type type; // type is int +``` + +You can test whether __result_of__ is using __decltype__ by checking if +the macro `BOOST_RESULT_OF_USE_DECLTYPE` is defined after +including `result_of.hpp`. You can also force __result_of__ to use +__decltype__ by defining `BOOST_RESULT_OF_USE_DECLTYPE` prior +to including `result_of.hpp`. + +If __decltype__ is not used, then automatic result type deduction of function +objects is not possible. Instead, __result_of__ uses the following protocol +to allow the programmer to specify a type. When `F` is a class type with a +member type `result_type`, `result_of::type` is +`F::result_type`. When `F` does not contain `result_type`, +`result_of::type` is +`F::result::type` when +`N > 0` or `void` when `N = 0`. + +Note that it is the responsibility of the programmer to ensure that +function objects accurately advertise their result +type via this protocol, as in the following example. + +``` +struct functor { + template struct result; + + template + struct result { + typedef T type; + }; + + template + T operator()(T x) + { + return x; + } +}; + +typedef __boost_result_of__::type type; // type is int +``` + +Since __decltype__ is a language feature standardized in C++11, if you are +writing a function object to be used with __result_of__, for maximum +portability, you might consider following the above protocol +even if your compiler has proper __decltype__ support. + +If you wish to continue to use the protocol on compilers that +support __decltype__, there are two options: + +* You can use __boost_tr1_result_of__, which is also defined in +[@../../../boost/utility/result_of.hpp ``]. + +* Alternatively, you can define the macro `BOOST_RESULT_OF_USE_TR1`, +which causes __result_of__ to use the protocol described above instead +of __decltype__. If you choose to follow the protocol, take care to +ensure that the `result_type` and `result<>` members accurately +represent the return type of `operator()` given a call expression. + +Additionally, __boost_result_of__ provides a third mode of operation, +which some users may find convenient. When +`BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK` is defined, +__boost_result_of__ behaves as follows. If the function object has a member +type `result_type` or member template `result<>`, then __boost_result_of__ +will use the TR1 protocol. + +Otherwise, __boost_result_of__ will use __decltype__. Using TR1 with +a __decltype__ fallback may workaround certain problems at the cost of portability. +For example: + +* Deficient compiler: If your code requires __boost_result_of__ to work +with incomplete return types but your compiler's __decltype__ implementation +does not support incomplete return types, then you can use the TR1 protocol +as a workaround. Support for incomplete return types was added late in the +C++11 standardization process +(see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf N3276]) +and is not implemented by some compilers. + +* Deficient legacy code: If your existing TR1 function object advertises a different type than +the actual result type deduced by __decltype__, then using TR1 with a __decltype__ fallback +will allow you to work with both your existing TR1 function objects and new C++11 +function object. This situation could occur if your legacy function objects +misused the TR1 protocol. See the documentation on known [link sec:result_of_tr1_diff differences] +between __boost_result_of__ and TR1. + +* [#BOOST_NO_RESULT_OF] This implementation of __result_of__ requires class template +partial specialization, the ability to parse function types properly, and support +for SFINAE. If __result_of__ is not supported by your compiler, including the header +[@../../../boost/utility/result_of.hpp ``] will define +the macro `BOOST_NO_RESULT_OF`. + +For additional information about __result_of__, see the C++ Library +Technical Report, [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf N1836], +or, for motivation and design rationale, the __result_of__ +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html proposal]. + +[#sec:result_of_guidelines] +[heading Usage guidelines for __boost_result_of__] + +The following are general suggestions about when and how to use __boost_result_of__. + +# If you are targeting C++11 and are not concerned about portability to +non-compliant compilers or previous versions of the standard, then use +`__std_result_of__`. If `__std_result_of__` meets your needs, then +there's no reason to stop using it. + +# If you are targeting C++11 but may port your code to legacy compilers +at some time in the future, then use __boost_result_of__ with __decltype__. +When __decltype__ is used __boost_result_of__ and `__std_result_of__` are usually +interchangeable. See the documentation on known [link sec:result_of_cxx11_diff differences] +between __boost_result_of__ and C++11 __std_result_of__. + +# If compiler portability is required, use __boost_result_of__ with the TR1 protocol + +Regardless of how you configure __boost_result_of__, it is +important to bear in mind that the return type of a +function may change depending on its arguments, and +additionally, the return type of a member function may +change depending on the cv-qualification of the +object. __boost_result_of__ must be passed +the appropriately cv-qualified types in order to +deduce the corresponding return type. + +For example: + +``` +struct functor { + int& operator()(int); + int const& operator()(int) const; + + float& operator()(float&); + float const& operator()(float const&); +}; + +typedef __boost_result_of__< + functor(int) +>::type type1; // type1 is int & + +typedef __boost_result_of__< + const functor(int) +>::type type2; // type2 is int const & + +typedef __boost_result_of__< + functor(float&) +>::type type3; // type3 is float & + +typedef __boost_result_of__< + functor(float const&) +>::type type4; // type4 is float const & +``` + +[#sec:result_of_tr1_protocol_guidelines] +[heading Usage guidelines for the TR1 result_of protocol] + +On compliant C++11 compilers, __boost_result_of__ can +use __decltype__ to deduce the type of any +call expression, including calls to function +objects. However, on pre-C++11 compilers or on +compilers without adequate decltype support, +additional scaffolding is needed from function +objects as described above. The following are +suggestions about how to use the TR1 protocol. + +* When the return type does not depend on the +argument types or the cv-qualification of the +function object, simply +define `result_type`. There is no need +to use the `result` template unless the +return type varies. + +* Use the protocol specified type when defining +function prototypes. This can help ensure the +actual return type does not get out of sync with +the protocol specification. For example: + +``` +struct functor { + typedef int result_type; + result_type operator()(int); +}; +``` + +* Always specify the `result` specialization near the corresponding +`operator()` overload. This can make it easier to keep the specializations +in sync with the overloads. For example: + +``` +struct functor { + template struct result; + + template + struct result { + typedef int& type; + }; + result::type operator()(int); + + template + struct result { + typedef int const& type; + }; + result::type operator()(int) const; +}; +``` + +* Use type transformations to simplify +the `result` template specialization. For +example, the following uses [@../type_traits/doc/html/index.html Boost.TypeTraits] +to specialize the `result` template for +a single `operator()` that can be called on +both a const and non-const function object with +either an lvalue or rvalue argument. + +``` +struct functor { + template struct result; + + template + struct result + : boost::remove_cv< + typename boost::remove_reference::type + > + {}; + + template + T operator()(T const& x) const; +}; +``` + +[#sec:result_of_tr1_diff] +[heading Known differences between __boost_result_of__ and __boost_tr1_result_of__] + +When using __decltype__, __boost_result_of__ ignores the TR1 protocol and instead deduces the +return type of function objects directly via __decltype__. In most situations, users +will not notice a difference, so long as they use the protocol correctly. The following are situations in +which the type deduced by __boost_result_of__ is known to differ depending on whether +__decltype__ or the TR1 protocol is used. + +TR1 protocol misusage: When using the TR1 protocol, __boost_result_of__ cannot +detect whether the actual type of a call to a function object is the same as the +type specified by the protocol, which allows for the possibility of inadvertent +mismatches between the specified type and the actual type. When using __decltype__, +these subtle bugs may result in compilation errors. For example: + +``` +struct functor { + typedef short result_type; + int operator()(short); +}; + +#ifdef BOOST_RESULT_OF_USE_DECLTYPE + +BOOST_STATIC_ASSERT(( + boost::is_same<__boost_result_of__::type, int>::value +)); + +#else + +BOOST_STATIC_ASSERT(( + boost::is_same<__boost_result_of__::type, short>::value +)); + +#endif +``` + +Note that the user can force __boost_result_of__ to use the TR1 +protocol even on platforms that support __decltype__ by +defining `BOOST_RESULT_OF_USE_TR1`. + +Nullary function objects: When using the TR1 protocol, __boost_result_of__ +cannot always deduce the type of calls to nullary function objects, in which case the +type defaults to void. When using __decltype__, __boost_result_of__ always gives the +actual type of the call expression. For example: + +``` +struct functor { + template struct result { + typedef int type; + }; + int operator()(); +}; + +#ifdef BOOST_RESULT_OF_USE_DECLTYPE + +BOOST_STATIC_ASSERT(( + boost::is_same<__boost_result_of__::type, int>::value +)); + +#else + +BOOST_STATIC_ASSERT(( + boost::is_same<__boost_result_of__::type, void>::value +)); + +#endif +``` + +Note that there are some workarounds for the nullary function problem. +So long as the return type does not vary, `result_type` can always be used to +specify the return type regardless of arity. If the return type does vary, +then the user can specialize __boost_result_of__ itself for nullary calls. + +Non-class prvalues and cv-qualification: When using the TR1 protocol, __boost_result_of__ will +report the cv-qualified type specified by `result_type` or the `result` template regardless of +the actual cv-qualification of the call expression. When using __decltype__, __boost_result_of__ +will report the actual type of the call expression, which is not cv-qualified when the expression +is a non-class prvalue. For example: + +``` +struct functor { + template struct result; + template struct result { + typedef const T type; + }; + + const short operator()(const short); + int const & operator()(int const &); +}; + +// Non-prvalue call expressions work the same with or without decltype. + +BOOST_STATIC_ASSERT(( + boost::is_same< + __boost_result_of__::type, + int const & +::value +)); + +// Non-class prvalue call expressions are not actually cv-qualified, +// but only the decltype-based result_of reports this accurately. + +#ifdef BOOST_RESULT_OF_USE_DECLTYPE + +BOOST_STATIC_ASSERT(( + boost::is_same< + __boost_result_of__::type, + short +::value +)); + +#else + +BOOST_STATIC_ASSERT(( + boost::is_same< + __boost_result_of__::type, + const short +::value +)); + +#endif +``` + +[#sec:result_of_cxx11_diff] +[heading Known differences between __boost_result_of__ and C++11 result_of] + +When using __decltype__, __boost_result_of__ implements most of the C++11 __std_result_of__ +specification. One known exception is that __boost_result_of__ does not implement the +requirements regarding pointers to member data. + +[heading Acknowledgments] + +Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others. + +[endsect] + + diff --git a/doc/string_ref.qbk b/doc/string_ref.qbk deleted file mode 100644 index 12a8362..0000000 --- a/doc/string_ref.qbk +++ /dev/null @@ -1,172 +0,0 @@ -[/ - / Copyright (c) 2012 Marshall Clow - / - / Distributed under 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) - /] - -[article String_Ref - [quickbook 1.5] - [authors [Clow, Marshall]] - [copyright 2012 Marshall Clow] - [license - Distributed under 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]) - ] -] - -[/===============] -[section Overview] -[/===============] - -Boost.StringRef is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442: -string_ref: a non-owning reference to a string]. - -When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. The canonical way to do this is as a `std::string`, but that has certain drawbacks: - -1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data. - -2) if a routine receives a constant `std::string` and wants to pass a portion of that string to another routine, then it must create a new string of that substring. - -3) A routine receives a constant `std::string` and wants to return a portion of the string, then it must create a new string to return. - -`string_ref` is designed to solve these efficiency problems. A `string_ref` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_ref` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to. - -A `string_ref` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_ref` is cheap to create and cheap to copy. - -`string_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work) - -Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. Like `std::string`, `string_ref` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end". - -Because a `string_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does. - -[endsect] - - -[/===============] -[section Examples] -[/===============] - -Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`. - - std::string extract_part ( const std::string &bar ) { - return bar.substr ( 2, 3 ); - } - - if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ } - -Let's figure out what happens in this (contrived) example. - -First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. Then a second string is created in the call `std::string::substr` and returned to `extract_part` (this copy may be elided by RVO). Then `extract_part` returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well. - -Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data. - -Now let's look at the same code with `string_ref`: - - boost::string_ref extract_part ( boost::string_ref bar ) { - return bar.substr ( 2, 3 ); - } - - if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } - -No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations. - -[endsect] - - -[/=================] -[section:reference Reference ] -[/=================] - -The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` . - -`#include ` - -Construction and copying: - - BOOST_CONSTEXPR basic_string_ref (); // Constructs an empty string_ref - BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string - BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair - template - basic_string_ref(const std::basic_string& str); // Constructs from a std::string - basic_string_ref (const basic_string_ref &rhs); - basic_string_ref& operator=(const basic_string_ref &rhs); - -`string_ref` does not define a move constructor nor a move-assignment operator because copying a `string_ref` is just a cheap as moving one. - -Basic container-like functions: - - BOOST_CONSTEXPR size_type size() const ; - BOOST_CONSTEXPR size_type length() const ; - BOOST_CONSTEXPR size_type max_size() const ; - BOOST_CONSTEXPR bool empty() const ; - - // All iterators are const_iterators - BOOST_CONSTEXPR const_iterator begin() const ; - BOOST_CONSTEXPR const_iterator cbegin() const ; - BOOST_CONSTEXPR const_iterator end() const ; - BOOST_CONSTEXPR const_iterator cend() const ; - const_reverse_iterator rbegin() const ; - const_reverse_iterator crbegin() const ; - const_reverse_iterator rend() const ; - const_reverse_iterator crend() const ; - -Access to the individual elements (all of which are const): - - BOOST_CONSTEXPR const charT& operator[](size_type pos) const ; - const charT& at(size_t pos) const ; - BOOST_CONSTEXPR const charT& front() const ; - BOOST_CONSTEXPR const charT& back() const ; - BOOST_CONSTEXPR const charT* data() const ; - -Modifying the `string_ref` (but not the underlying data): - - void clear(); - void remove_prefix(size_type n); - void remove_suffix(size_type n); - -Searching: - - size_type find(basic_string_ref s) const ; - size_type find(charT c) const ; - size_type rfind(basic_string_ref s) const ; - size_type rfind(charT c) const ; - size_type find_first_of(charT c) const ; - size_type find_last_of (charT c) const ; - - size_type find_first_of(basic_string_ref s) const ; - size_type find_last_of(basic_string_ref s) const ; - size_type find_first_not_of(basic_string_ref s) const ; - size_type find_first_not_of(charT c) const ; - size_type find_last_not_of(basic_string_ref s) const ; - size_type find_last_not_of(charT c) const ; - -String-like operations: - - BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref - bool starts_with(charT c) const ; - bool starts_with(basic_string_ref x) const ; - bool ends_with(charT c) const ; - bool ends_with(basic_string_ref x) const ; - -[endsect] - -[/===============] -[section History] -[/===============] - -[heading boost 1.71] -* Glen Fernandes updated the implementation of the stream insertion operator to -write directly to the `basic_streambuf` and refactored that functionality into -a common utility. - -[heading boost 1.53] -* Introduced - - -[endsect] - - - - diff --git a/doc/string_view.qbk b/doc/string_view.qbk new file mode 100644 index 0000000..5c37265 --- /dev/null +++ b/doc/string_view.qbk @@ -0,0 +1,199 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / Distributed under 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) + /] + +[/===============] +[section String View] +[/===============] + +[heading Introduction] + +The class __boost_string_view__ and other classes derived from __basic_string_view__ represent references to strings or substrings. When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. Before __std_string_view__, the canonical way to do this used to be a __std_string__, but that has certain drawbacks: + +1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data. + +2) If a routine receives a constant __std_string__ and wants to pass a portion of that string to another routine, then it must create a new string of that substring. + +3) If a routine receives a constant __std_string__ and wants to return a portion of the string, then it must create a new string to return. + +__boost_string_view__ is designed to solve these efficiency problems. A __boost_string_view__ is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of __std_string__. A __boost_string_view__ is cheap to create, copy and pass by value, because it does not actually own the storage that it points to. + +A __boost_string_view__ is implemented as a small struct that contains a pointer to the start of the character `data` and a `count`. A __boost_string_view__ is cheap to create and cheap to copy. + +__boost_string_view__ acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator[]`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you do not need to change the underlying data. For example, __std_sort__ and __std_remove__ will not work. + +Besides generic container functionality, __boost_string_view__ provides a subset of the interface of __std_string__. This makes it easy to replace parameters of type `const __std_string__ &` with __boost_string_view__. Like __std_string__, __boost_string_view__ has a static member variable named `npos` to denote the result of failed searches, and to mean "the end". + +[caution Because a __boost_string_view__ does not own the data that it refers to, it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a __string_view__ refers to exists as long as the __string_view__ does.] + +[note + +Boost.Utility also includes the class __string_ref__: + +- __string_ref__ is the initial implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442: +string_ref: a non-owning reference to a string]. + +- __string_view__ is an updated implementation to reflect the Library Fundamentals TS [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html N4480: \[string.view\]] + +Please prefer __string_view__ / __basic_string_view__ over __string_ref__ / __basic_string_ref__: + +- The __basic_string_view__ class better matches __std_basic_string_view__ + +- __basic_string_view__ has WAY more constexpr support. + +- Code that uses __basic_string_ref__ should continue to work. + +- No much code depends on __basic_string_ref__ anymore + + +] + +[/===============] +[heading Examples] +[/===============] + +Integrating __string_view__ into your code is fairly simple. Wherever you pass a `const __std_string__ &` or __std_string__ as a parameter, that's a candidate for passing a __boost_string_view__. + +``` +__std_string__ extract_part ( const __std_string__ &bar ) { + return bar.substr ( 2, 3 ); +} + +if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ } +``` + +Let's figure out what happens in this contrived example. + +* First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. +* Then a second string is created in the call `__std_string__::substr` and returned to `extract_part` (this copy may be elided by RVO). +* Then `extract_part` returns that string back to the caller (again this copy may be elided). +* The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well. + +Two __std_string__ s are created, and two copy operations. That is potentially four memory allocations and deallocations, and the associated copying of data. + +Now let's look at the same code with __string_view__: + +``` +__boost_string_view__ extract_part ( __boost_string_view__ bar ) { + return bar.substr ( 2, 3 ); +} + +if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } +``` + +No memory allocations. No copying of character data. No changes to the code other than the types. There are two __string_view__ s created, and two __string_view__ s copied, but those are cheap operations. + +[/=================] +[heading:reference Synopsis ] +[/=================] + +The header file [@../../../include/boost/utility/string_view.hpp ``] defines a template __boost_basic_string_view__, and four specializations __string_view__, __wstring_view__, __u16string_view__, __u32string_view__ - for `char` / `wchar_t` / `char16_t` / `char32_t`. + +`#include ` + +Construction and copying: + +``` +constexpr basic_string_view (); // Constructs an empty string_view +constexpr basic_string_view(const charT* str); // Constructs from a NULL-terminated string +constexpr basic_string_view(const charT* str, size_type len); // Constructs from a pointer, length pair +template +basic_string_view(const __std_basic_string__& str); // Constructs from a std::string +basic_string_view (const basic_string_view &rhs); +basic_string_view& operator=(const basic_string_view &rhs); +``` + +__string_view__ does not define a move constructor nor a move-assignment operator because copying a __string_view__ is just a cheap as moving one. + +Basic container-like functions: + +``` +constexpr size_type size() const ; +constexpr size_type length() const ; +constexpr size_type max_size() const ; +constexpr bool empty() const ; + +// All iterators are const_iterators +constexpr const_iterator begin() const ; +constexpr const_iterator cbegin() const ; +constexpr const_iterator end() const ; +constexpr const_iterator cend() const ; +const_reverse_iterator rbegin() const ; +const_reverse_iterator crbegin() const ; +const_reverse_iterator rend() const ; +const_reverse_iterator crend() const ; +``` + +Access to the individual elements (all of which are const): + +``` +constexpr const charT& operator[](size_type pos) const ; +const charT& at(size_t pos) const ; +constexpr const charT& front() const ; +constexpr const charT& back() const ; +constexpr const charT* data() const ; +``` + +Modifying the __string_view__ (but not the underlying data): + +``` +void clear(); +void remove_prefix(size_type n); +void remove_suffix(size_type n); +``` + +Searching: + +``` +size_type find(basic_string_view s) const ; +size_type find(charT c) const ; +size_type rfind(basic_string_view s) const ; +size_type rfind(charT c) const ; +size_type find_first_of(charT c) const ; +size_type find_last_of (charT c) const ; + +size_type find_first_of(basic_string_view s) const ; +size_type find_last_of(basic_string_view s) const ; +size_type find_first_not_of(basic_string_view s) const ; +size_type find_first_not_of(charT c) const ; +size_type find_last_not_of(basic_string_view s) const ; +size_type find_last_not_of(charT c) const ; +``` + +String-like operations: + +``` +constexpr basic_string_view substr(size_type pos, size_type n=npos) const ; // Creates a new string_view +bool starts_with(charT c) const ; +bool starts_with(basic_string_view x) const ; +bool ends_with(charT c) const ; +bool ends_with(basic_string_view x) const ; +``` + +[/===============] +[h1 History] +[/===============] + +[h5 boost 1.71] +* Glen Fernandes updated the implementation of the stream insertion operator to +write directly to the `basic_streambuf` and refactored that functionality into +a common utility. + +[h5 boost 1.53] +* Introduced + +[heading Acknowledgments] + +Author: Clow, Marshall + +Copyright 2012 Marshall Clow + +[endsect] + + + + diff --git a/doc/value_init.qbk b/doc/value_init.qbk new file mode 100644 index 0000000..75014c5 --- /dev/null +++ b/doc/value_init.qbk @@ -0,0 +1,564 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / Distributed under 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) + /] + +[/===============] +[#sec:value_init] +[section Value Init] +[/===============] + +[heading Introduction] + +Constructing and initializing objects in a generic way is difficult in +C++. The problem is that there are several different rules that apply +for initialization. Depending on the type, the value of a newly constructed +object can be zero-initialized (logically 0), default-constructed (using +the default constructor), or indeterminate. When writing generic code, +this problem must be addressed. The template __value_initialized__ provides +a solution with consistent syntax for value initialization of scalar, +union and class types. Moreover, __value_initialized__ offers a workaround to various +compiler issues regarding value-initialization. + +Furthermore, a `const` object __initialized_value__ is provided, +to avoid repeating the type name when retrieving the value from a +`__value_initialized__` object. + +There are various ways to initialize a variable, in C++. The following +declarations all ['may] have a local variable initialized to its default +value: + +``` +T1 var1; +T2 var2 = 0; +T3 var3 = {}; +T4 var4 = T4(); +``` + +Unfortunately, whether or not any of those declarations correctly +initialize the variable very much depends on its type. The first +declaration is valid for any __DefaultConstructible__ type by definition. + +However, it does not always do an initialization. It correctly initializes +the variable when it's an instance of a class, and the author of the class +has provided a proper default constructor. On the other hand, the value of +`var1` is ['indeterminate] when its type is an arithmetic type, like `int`, +`float`, or `char`. + +An arithmetic variable is of course initialized properly by the second declaration, +`T2 var2 = 0`. But this initialization form will not usually work for a +class type, unless the class was especially written to support being +initialized that way. + +The third form, `T3 var3 = {}`, initializes an aggregate, typically a "C-style" +`struct` or a "C-style" array. However, at the time this library was developed, +the syntax did not allow for a class that has an explicitly declared constructor. + +The fourth form is the most generic form of them, as it can be used to initialize +arithmetic types, class types, aggregates, pointers, and other types. +The declaration, `T4 var4 = T4()`, should be read as follows: First a temporary +object is created, by `T4()`. This object is [link sec:valueinit value-initialized]. +Next the temporary object is copied to the named variable, `var4`. Afterwards, +the temporary is destroyed. While the copying and the destruction are likely to +be optimized away, C++ still requires the type `T4` to be __CopyConstructible__. +So `T4` needs to be ['both] __DefaultConstructible__ ['and] __CopyConstructible__. + +A class may not be CopyConstructible, for example because it may have a +private and undefined copy constructor, or because it may be derived from +`boost::noncopyable`. Scott Meyers \[[link sec:references 2]\] explains why a +class would be defined like that. + +There is another, less obvious disadvantage to the fourth form, `T4 var4 = T4()`: +It suffers from various [link sec:compiler_issues compiler issues], causing +a variable to be left uninitialized in some compiler specific cases. + +The template __value_initialized__ offers a generic way to initialize +an object, like `T4 var4 = T4()`, but without requiring its type +to be __CopyConstructible__. And it offers a workaround to those compiler issues +regarding value-initialization as well. It allows getting an initialized +variable of any type; it ['only] requires the type to be __DefaultConstructible__. +A properly ['value-initialized] object of type `T` is constructed by the following +declaration: + +``` +value_initialized var; +``` + +The template __initialized__ offers both value-initialization and direct-initialization. +It is especially useful as a data member type, allowing the very same object +to be either direct-initialized or value-initialized. + +The `const` object __initialized_value__ allows value-initializing a variable as follows: + +``` +T var = initialized_value; +``` + +This form of initialization is semantically equivalent to `T4 var4 = T4()`, +but robust against the aforementioned compiler issues. + +[#sec:details] +[heading Details] + +The C++ standard \[[link sec:references 3]\] contains the definitions +of `zero-initialization` and `default-initialization`. Informally, zero-initialization +means that the object is given the initial value `0` converted to the type and +default-initialization means that POD \[[link sec:references 4]\] types are zero-initialized, +while non-POD class types are initialized with their corresponding default constructors. + +A ['declaration] can contain an ['initializer], which specifies the +object's initial value. The initializer can be just '()', which states that +the object shall be value-initialized (but see below). However, if a ['declaration] +has no ['initializer] and it is of a non-`const`, non-`static` POD type, the +initial value is indeterminate: (see §8.5, [dcl.init], for the +accurate definitions). + +``` +int x; // no initializer. x value is indeterminate. +__std_string__ s; // no initializer, s is default-constructed. + +int y = int(); +// y is initialized using copy-initialization +// but the temporary uses an empty set of parentheses as the initializer, +// so it is default-constructed. +// A default constructed POD type is zero-initialized, +// therefore, y == 0. + +void foo ( __std_string__ ) ; +foo ( __std_string__() ) ; +// the temporary string is default constructed +// as indicated by the initializer () +``` + +[#sec:valueinit] +[h5 value-initialization] + +The first [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html Technical +Corrigendum for the C++ Standard] (TC1), whose draft was released to the public in +November 2001, introduced [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#178 Core +Issue 178], among many other issues. + +That issue introduced the new concept of `value-initialization`, and also fixed the +wording for zero-initialization. Informally, value-initialization is similar to +default-initialization with the exception that in some cases non-static data members +and base class sub-objects are also value-initialized. + +The difference is that an object that is value-initialized will not have, or at least +is less likely to have, indeterminate values for data members and base class sub-objects; +unlike the case of an object default constructed (see Core Issue 178 for a +normative description). + +In order to specify value-initialization of an object we need to use the +empty-set initializer: `()`. + +As before, a declaration with no initializer specifies default-initialization, +and a declaration with a non-empty initializer specifies copy (`=xxx`) or +direct (`xxx`) initialization. + +``` +template void eat(T); + +int x ; // indeterminate initial value. + +__std_string__ s; // default-initialized. + +eat ( int() ) ; // value-initialized + +eat ( __std_string__() ) ; // value-initialized +``` + +[#sec:valueinitsyn] +[h5 value-initialization syntax] + +Value initialization is specified using `()`. However, the empty set of +parentheses is not permitted by the syntax of initializers because it is +parsed as the declaration of a function taking no arguments: + +``` +int x() ; // declares function int(*)() +``` + +Thus, the empty `()` must be put in some other initialization context. + +One alternative is to use copy-initialization syntax: + +``` +int x = int(); +``` + +This works perfectly fine for POD types. But for non-POD class types, +copy-initialization searches for a suitable constructor, which could be, +for instance, the copy-constructor. It also searches for a suitable conversion +sequence but this does not apply in this context. + +For an arbitrary unknown type, using this syntax may not have the +value-initialization effect intended because we don't know if a copy +from a default constructed object is exactly the same as a default +constructed object, and the compiler is allowed, in +some cases, but never required to, optimize the copy away. + +One possible generic solution is to use value-initialization of a non static +data member: + +``` +template +struct W +{ + // value-initialization of 'data' here. + W() : data() {} + + T data; +}; + +W w; +// w.data is value-initialized for any type. +``` + +This is the solution as it was supplied by earlier versions of the +`__value_initialized__` template class. Unfortunately this approach +suffered from various compiler issues. + +[#sec:compiler_issues] +[h5 Compiler issues] + +Various compilers have not yet fully implemented value-initialization. +So when an object should be ['value-initialized] according to the C++ Standard, +it ['may] in practice still be left uninitialized, because of those +compiler issues. It is hard to make a general statement on what those issues +are like, because they depend on the compiler you are using, its version number, +and the type of object you would like to have value-initialized. + +All compilers we have tested so far support value-initialization for arithmetic types properly. +However, various compilers may leave some types of ['aggregates] uninitialized, when they +should be value-initialized. Value-initialization of objects of a pointer-to-member type may also +go wrong on various compilers. + +At the moment of writing, May 2010, the following reported issues regarding +value-initialization are still there in current compiler releases: + + + +* [@https://connect.microsoft.com/VisualStudio/feedback/details/100744 Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression]: Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005. +* [@http://connect.microsoft.com/VisualStudio/feedback/details/484295 Microsoft Visual Studio Feedback ID 484295, VC++ does not value-initialize members of derived classes without user-declared constructor] Reported by Sylvester Hesp, 2009. +* [@https://connect.microsoft.com/VisualStudio/feedback/details/499606 Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization] Reported by Alex Vakulenko, 2009 +* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83751 Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized] Reported by Niels Dekker (LKEB), 2010. +* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83851 Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798] Reported by Niels Dekker, 2010. +* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=84279 Embarcadero/C++Builder Report 84279, Internal compiler error (F1004), value-initializing member function pointer by "new T()"] Reported by Niels Dekker, 2010 +* Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate. Reported to Steve Clamage by Niels Dekker, 2010. +* IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate. Reported to Michael Wong by Niels Dekker, 2010. +* Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error on Intel 11.1. Reported by John Maddock, 2010. + +Note that all known GCC issues regarding value-initialization are fixed with GCC version 4.4, including +[@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 GCC Bug 30111]. Clang also has completely implemented +value-initialization, as far as we know, now that [@http://llvm.org/bugs/show_bug.cgi?id=7139 Clang Bug 7139] +is fixed. + +New versions of __value_initialized__ (Boost release version 1.35 or higher) offer a workaround to these +issues: __value_initialized__ may now clear its internal data, prior to constructing the object that it +contains. It will do so for those compilers that need to have such a workaround, based on the +[@boost:/doc/html/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects +compiler defect macro] `BOOST_NO_COMPLETE_VALUE_INITIALIZATION`. + +[#sec:types] +[heading Types and objects] + +[#sec:val_init] +[heading `template class value_initialized`] + +``` +namespace boost { + +template +class __value_initialized__ +{ + + public : + + __value_initialized__() : x() {} + + operator T const &() const { return x ; } + + operator T&() { return x ; } + + T const &data() const { return x ; } + + T& data() { return x ; } + + void swap( __value_initialized__& ); + + private : + + [unspecified] x ; + +} ; + +template + +T const& get ( __value_initialized__ const& x ) +{ + return x.data(); +} + +template +T& get ( __value_initialized__& x ) +{ + return x.data(); +} + +template +void swap ( __value_initialized__& lhs, __value_initialized__& rhs ) +{ + lhs.swap(rhs); +} + +} // namespace boost +``` + +An object of this template class is a `T`-wrapper convertible to `'T&'` whose +wrapped object (data member of type `T`) is [link sec:valueinit value-initialized] upon default-initialization +of this wrapper class: + +``` +int zero = 0; +__value_initialized__ x; +assert( x == zero ) ; + +__std_string__ def; +__value_initialized__< __std_string__ > y; +assert( y == def ) ; +``` + +The purpose of this wrapper is to provide a consistent syntax for value initialization +of scalar, union and class types (POD and non-POD) since the correct syntax for value +initialization varies (see [link sec:valueinitsyn value-initialization syntax]). + +The wrapped object can be accessed either through the conversion operator +`T&`, the member function `data()`, or the non-member function `get()`: + +``` +void watch(int); + +__value_initialized__ x; + +watch(x) ; // operator T& used. +watch(x.data()); +watch( get(x) ) // function get() used +``` + +Both `const` and non-`const` objects can be wrapped. Mutable objects can be +modified directly from within the wrapper but constant objects cannot: + +When `T` is a __Swappable__ type, `__value_initialized__` +is swappable as well, by calling its `swap` member function +as well as by calling `boost::swap`. + +``` +__value_initialized__ x; +static_cast(x) = 1 ; // OK +get(x) = 1 ; // OK + +__value_initialized__ y ; +static_cast(y) = 1 ; // ERROR: cannot cast to int& +static_cast(y) = 1 ; // ERROR: cannot modify a const value +get(y) = 1 ; // ERROR: cannot modify a const value +``` + +[warning + +The __value_initialized__ implementation of Boost version 1.40.0 and older +allowed ['non-const] access to the wrapped object, from a constant wrapper, +both by its conversion operator and its `data()` member function. + +For example: + +``` +__value_initialized__ const x_c; +int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const. +xr = 2 ; +``` + +The reason for this obscure behavior was that some compilers did not accept the following valid code: + +``` +struct X +{ + operator int&() ; + operator int const&() const ; + }; + X x ; + (x == 1) ; // ERROR HERE! +``` + +The current version of __value_initialized__ no longer has this obscure behavior. +As compilers nowadays widely support overloading the conversion operator by having a `const` +and a `non-const` version, we have decided to fix the issue accordingly. So the current version +supports the idea of logical constness. + +] + +[h5 Recommended practice: The non-member get() idiom] + +The obscure behavior of being able to modify a non-`const` +wrapped object from within a constant wrapper (as was supported by previous +versions of __value_initialized__) can be avoided if access to the wrapped object +is always performed with the `get()` idiom: + +``` +value_initialized x; +get(x) = 1; // OK +value_initialized cx; +get(x) = 1; // ERROR: Cannot modify a const object + +value_initialized const x_c; +get(x_c) = 1; // ERROR: Cannot modify a const object + +value_initialized const cx_c; +get(cx_c) = 1; // ERROR: Cannot modify a const object +``` + +[#sec:initialized] +[heading `template class initialized`] + + +``` +namespace boost { + +template +class __initialized__ +{ + + public : + + __initialized__() : x() {} + + explicit __initialized__(T const & arg) : x(arg) {} + + operator T const &() const; + + operator T&(); + + T const &data() const; + + T& data(); + + void swap( __initialized__& ); + + private : + + [unspecified] x ; + +}; + +template +T const& get ( __initialized__ const& x ); + +template +T& get ( __initialized__& x ); + +template +void swap ( __initialized__& lhs, __initialized__& rhs ); + +} // namespace boost +``` + +The template class `boost::__initialized__` supports both value-initialization +and direct-initialization, so its interface is a superset of the interface +of `__value_initialized__`: Its default-constructor value-initializes the +wrapped object just like the default-constructor of `__value_initialized__`, +but `boost::__initialized__` also offers an extra `explicit` +constructor, which direct-initializes the wrapped object by the specified value. + +`__initialized__` is especially useful when the wrapped +object must be either value-initialized or direct-initialized, depending on +runtime conditions. For example, `__initialized__` could +hold the value of a data member that may be value-initialized by some +constructors, and direct-initialized by others. + +On the other hand, if it is known beforehand that the +object must ['always] be value-initialized, `__value_initialized__` +may be preferable. And if the object must always be +direct-initialized, none of the two wrappers really needs to be used. + +[#sec:initialized_value] +[heading `initialized_value`] + +``` +namespace boost { +class __initialized_value_t__ +{ + public : + template operator T() const ; +}; + +__initialized_value_t__ const initialized_value = {} ; + +} // namespace boost +``` + +__initialized_value__ provides a convenient way to get +an initialized value: its conversion operator provides an appropriate +['value-initialized] object for any __CopyConstructible__ type. + +Suppose you need to have an initialized variable of type `T`. +You could do it as follows: + +``` +T var = T(); +``` + +But as mentioned before, this form suffers from various compiler issues. +The template __value_initialized__ offers a workaround: + +``` +T var = get( __value_initialized__() ); +``` + +Unfortunately both forms repeat the type name, which +is rather short now (`T`), but could of course be +more like `Namespace::Template::Type`. + +Instead, one could use __initialized_value__ as follows: + +``` +T var = __initialized_value__; +``` + +[#sec:references] +[h5 References] + +# Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote various papers, +proposing to extend the support for brace-enclosed ['initializer lists] +in C++. This [@https://en.cppreference.com/w/cpp/language/list_initialization feature] has +now been available since C++11. This would allow a variable `var` of any __DefaultConstructible__ type +`T` to be ['value-initialized] by doing `T var = {}`. The papers are listed at Bjarne's web page, +[@http://www.research.att.com/~bs/WG21.html My C++ Standards committee papers]. + +# Scott Meyers, Effective C++, Third Edition, item 6, ['Explicitly disallow the use of +compiler-generated functions you do not want], [@http://www.aristeia.com/books.html Scott Meyers: Books and CDs] + +# The C++ Standard, Second edition (2003), ISO/IEC 14882:2003 + +# POD stands for "Plain Old Data" + +[#sec:acknowledgements] +[h5 Acknowledgements] + +__value_initialized__ was developed by Fernando Cacciola, with help and suggestions +from David Abrahams and Darin Adler. + +Special thanks to Bjorn Karlsson who carefully edited and completed this documentation. + +__value_initialized__ was reimplemented by Fernando Cacciola and Niels Dekker +for Boost release version 1.35 (2008), offering a workaround to various compiler issues. + +`boost::__initialized__` was very much inspired by feedback from Edward Diener and Jeffrey Hellrung. + +__initialized_value__ was written by Niels Dekker, and added to Boost release version 1.36 (2008). + +Developed by [@mailto:fernando_cacciola@hotmail.com Fernando Cacciola]. The latest version of +this file can be found at [@http://www.boost.org www.boost.org]. + +[endsect] diff --git a/enable_if.html b/enable_if.html index 0cd1a98..d7ea199 100644 --- a/enable_if.html +++ b/enable_if.html @@ -1,15 +1,19 @@ - - -Automatic redirection + Boost.Utility + Automatic redirection failed, please go to -enable_if.html
-

© Copyright Beman Dawes, 2001

-

Distributed under the Boost Software License, Version 1.0. (See accompanying -file LICENSE_1_0.txt or copy -at www.boost.org/LICENSE_1_0.txt)

+../core/doc/html/core/enable_if.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/identity_type/index.html b/identity_type/index.html index 00b3362..f4bdcb1 100644 --- a/identity_type/index.html +++ b/identity_type/index.html @@ -6,7 +6,7 @@ Automatic redirection failed, click this link  
-

© Copyright Lorenzo Caminiti, 2009-2012

+

Copyright © Lorenzo Caminiti, 2009-2012

Distributed under the Boost Software License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a copy at diff --git a/in_place_factories.html b/in_place_factories.html index 8eb7ea8..48a57f9 100644 --- a/in_place_factories.html +++ b/in_place_factories.html @@ -1,296 +1,19 @@ - - - - - - -In_place_factory Documentation - - - -

- -
-
-
-
-
-
-

Header <boost/utility/in_place_factory.hpp>

- -

Header <boost/utility/typed_in_place_factory.hpp>

- -
-
-
-
-
-
-

 

- -

Contents

-
-
Motivation
-
Framework
-
Specification
-
Container-side Usage
-
User-side Usage
-
- -
- -

Motivation

- -

Suppose we have a class

-
struct X
-{
-  X ( int, std::string ) ;
-} ;
-

And a container for it which supports an empty state (that is, which can contain zero objects):

-
struct C
-{
-   C() : contained_(0) {}
-  ~C() { delete contained_ ; }
-  X* contained_ ;
-} ;
-

A container designed to support an empty state typically doesn't require the contained type to be DefaultConstructible, -but it typically requires it to be CopyConstructible as a mechanism to -initialize the object to store:

-
struct C
-{
-   C() : contained_(0) {}
-   C ( X const& v ) : contained_ ( new X(v) ) {}
-  ~C() { delete contained_ ; }
-  X* contained_ ;
-} ;
-

There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction, -there must exist a previously constructed source object to copy from. This -object is likely to be temporary and serve no purpose besides being the source

-
void foo()
-{
-  // Temporary object created.
-  C c( X(123,"hello") ) ;
-}
-
-

A solution to this problem is to support direct construction of the contained -object right in the container's storage.
-In this scheme, the user supplies the arguments for the X constructor -directly to the container:

-
struct C
-{
-   C() : contained_(0) {}
-   C ( X const& v ) : contained_ ( new X(v) ) {}
-   C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {}
-  ~C() { delete contained_ ; }
-  X* contained_ ;
-} ;
-
void foo()
-{
-  // Wrapped object constructed in-place
-  // No temporary created.
-  C c(123,"hello") ;
-}
-
-

Clearly, this solution doesn't scale well since the container must duplicate all the constructor overloads from the contained type -(at least all those which are to be supported directly in the container).

- -

Framework

-

-This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring -the entire set of constructor overloads from the contained type. It also allows the container to remove the CopyConstuctible -requirement from the contained type since objects can be directly constructed in-place without need of a copy.
-The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized). -Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override -a fully-constructed object (as this would defeat the purpose of in-place construction) -

-

For this purpose, the framework provides two families of classes collectively called: InPlaceFactories and TypedInPlaceFactories.
-Essentially, these classes hold a sequence of actual parameters and a method to contruct an object in place using these parameters. -Each member of the family differs only in the number (and type) of the parameter list. The first family -takes the type of the object to construct directly in method provided for that -purpose, whereas the second family incorporates that type in the factory class -itself..

-

From the container POV, using the framework amounts to calling the factory's method to contruct the object in place. -From the user POV, it amounts to creating the right factory object to hold the parameters and pass it to the container.
-The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:

-
struct C
-{
-   template<class InPlaceFactory>
-   C ( InPlaceFactory const& aFactory )
-    :
-    contained_ ( uninitialized_storage() )
-   {
-     aFactory.template apply<X>(contained_);
-   }
-
-  ~C() 
-  { 
-    contained_ -> X::~X();
-    delete[] contained_ ; 
-  }
-
-  char* uninitialized_storage() { return new char[sizeof(X)] ; }
-
-  char* contained_ ;
-} ;
-
-void foo()
-{
-  C c( in_place(123,"hello") ) ;
-}
-
- -
- -

Specification

- -

The following is the first member of the family of 'in_place_factory' classes, along with its corresponding helper template function. -The rest of the family varies only in the number and type of template (and constructor) parameters.

-
namespace boost {
-
-struct in_place_factory_base {} ;
-
-template<class A0>
-class in_place_factory : public in_place_factory_base
-{
-  public:
- -
    in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
-
-    template< class T >
-    void apply ( void* address ) const
-    {
-      new (address) T(m_a0);
-    }
-
-  private:
- -
    A0 const& m_a0 ;
-} ;
-
-template<class A0>
-in_place_factory<A0> in_place ( A0 const& a0 )
-{
-  return in_place_factory<A0>(a0);
-}
-
- -

Similarly, the following is the first member of the family of 'typed_in_place_factory' classes, along with its corresponding -helper template function. The rest of the family varies only in the number and type of template (and constructor) parameters.

-
namespace boost {
-
-struct typed_in_place_factory_base {} ;
-
-template<class T, class A0>
-class typed_in_place_factory : public typed_in_place_factory_base
-{
-  public:
- -
    typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
-
-    void apply ( void* address ) const
-    {
-      new (address) T(m_a0);
-    }
-
-  private:
- -
    A0 const& m_a0 ;
-} ;
-
-template<class T, class A0>
-typed_in_place_factory<A0> in_place ( A0 const& a0 )
-{
-  return typed_in_place_factory<T,A0>(a0);
-}
- -
}
-
- -

As you can see, the 'in_place_factory' and 'typed_in_place_factory' template classes varies only in the way they specify -the target type: in the first family, the type is given as a template argument to the apply member function while in the -second it is given directly as part of the factory class.
-When the container holds a unique non-polymorphic type (such as the case of Boost.Optional), it knows the exact dynamic-type -of the contained object and can pass it to the apply() method of a (non-typed) factory. -In this case, end users can use an 'in_place_factory' instance which can be constructed without the type of the object to construct.
-However, if the container holds heterogeneous or polymorphic objects (such as the case of Boost.Variant), the dynamic-type -of the object to be constructed must be known by the factory itslef. In this case, end users must use a 'typed_in_place_factory' -instead.

- -
- -

Container-side Usage

- -

As shown in the introductory simplified example, the container class must -contain methods that accept an instance of -these factories and pass the object's storage to the factory's apply method.
-However, the type of the factory class cannot be completly specified in the container class because that would -defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list -for the constructor of its contained object.
-The correct function overload must be based on the only distinctive and common -characteristic of all the classes in each family, the base class.
-Depending on the container class, you can use 'enable_if' to generate the right overload, or use the following -dispatch technique (used in the Boost.Optional class): -

-
struct C
-{
-   C() : contained_(0) {}
-   C ( X const& v ) : contained_ ( new X(v) ) {}
-
-   template<class Expr>
-   C ( Expr const& expr )
-    :
-    contained_ ( uninitialized_storage() )
-   {
-    construct(expr,&expr)
-   }
-
-  ~C() { delete contained_ ; }
-
-  template<class InPlaceFactory>
-  void construct ( InPlaceFactory const& aFactory, boost::in_place_factory_base* )
-  {
-    aFactory.template apply<X>(contained_);
-  }
-
-  template<class TypedInPlaceFactory>
-  void construct ( TypedInPlaceFactory const& aFactory, boost::typed_in_place_factory_base* )
-  {
-    aFactory.apply(contained_);
-  }
-
-  X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; }
-
-  X* contained_ ;
-} ;
-
- + + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/utility/utilities/in_place_factory.html
- -

User-side Usage

- -

End users pass to the container an instance of a factory object holding the actual parameters needed to construct the -contained object directly within the container. For this, the helper template function 'in_place' is used.
-The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.
-The call 'in_place<T>(a0,a1,a2,...,an)' constructs a 'typed_in_place_factory' instance with the given argument list for the -type 'T'.

-
void foo()
-{
-  C a( in_place(123,"hello") ) ;    // in_place_factory passed
-  C b( in_place<X>(456,"world") ) ; // typed_in_place_factory passed
-}
-
- -

Revised September 17, 2004

-

© Copyright Fernando Luis Cacciola Carballal, 2004

-

Use, modification, and distribution are subject to the Boost Software -License, Version 1.0. (See accompanying file -LICENSE_1_0.txt or copy at -www.boost.org/LICENSE_1_0.txt)

-

Developed by Fernando Cacciola, -the latest version of this file can be found at www.boost.org, and the boost -discussion lists

- - + + Boost.Utility
+
+ Distributed under 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)
+
+
+ + diff --git a/index.html b/index.html index c2af44f..3f01470 100644 --- a/index.html +++ b/index.html @@ -1,50 +1,19 @@ - - - - - - Boost Utility Library - - -

Boost - Utility Library

-

The Boost Utility Library isn't really a single library at all. It is just a - collection for components too small to be called libraries in their own right.

-

But that doesn't mean there isn't useful stuff here. Take a look:

- -

Over time useful stuff here has moved to more appropriate Boost libraries:

- -
-

© Copyright Beman Dawes, 2001

-

Distributed under the Boost Software License, Version 1.0. (See - accompanying file - LICENSE_1_0.txt or copy at - - www.boost.org/LICENSE_1_0.txt)

-

Revised - 07 November, 2006

- + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
+ diff --git a/iterator_adaptors.htm b/iterator_adaptors.htm index 7232ac2..82a9935 100644 --- a/iterator_adaptors.htm +++ b/iterator_adaptors.htm @@ -1,11 +1,19 @@ - - - - + Boost.Utility + -This documentation moved to ../iterator/doc/index.html. +Automatic redirection failed, please go to +../iterator/doc/generator_iterator.htm +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
diff --git a/operators.htm b/operators.htm index 3ae2bcc..ca5e719 100644 --- a/operators.htm +++ b/operators.htm @@ -1,2220 +1,19 @@ - - - - - - - Header <boost/operators.hpp> Documentation - - - -

boost.png (6897 bytes)Header <boost/operators.hpp>

- -

The header <boost/operators.hpp> supplies - several sets of class templates (in namespace boost). These - templates define operators at namespace scope in terms of a minimal - number of fundamental operators provided by the class.

- -

Contents

- - - -

Rationale

- -

Overloaded operators for class types typically occur in groups. If you - can write x + y, you probably also want to be able - to write x += y. If you can write x < y, you - also want x > y, x >= y, and x <= y. - Moreover, unless your class has really surprising behavior, some of these - related operators can be defined in terms of others (e.g. x >= y - is equivalent to !(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.

- -

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 - (binary) +. Two-argument forms of the - templates are also provided to allow interaction with other types.

- -

Summary of Template Semantics

- -
    -
  1. Each operator template completes the concept(s) it describes by - defining overloaded operators for its target class.
  2. - -
  3. The name of an operator class template indicates the concept that its target class will model.
  4. - -
  5. Usually, the target class uses an instantation of the operator - class template as a base class. Some operator templates support an alternate method.
  6. - -
  7. The concept can be compound, i.e. it may represent a common - combination of other, simpler concepts.
  8. - -
  9. Most operator templates require their target class to support - operations related to the operators supplied by the template. In - accordance with widely accepted coding style recommendations, the - target class is often required to supply the assignment counterpart - operator of the concept's "main operator." For example, the - addable template requires operator+=(T - const&) and in turn supplies operator+(T const&, T - const&).
  10. -
- -

Use of concepts

- -

The discussed concepts are not necessarily the standard library's - concepts (CopyConstructible, etc.), although some of them could - be; they are what we call concepts with a small 'c'. In - particular, they are different from the former ones in that they do - not describe precise semantics of the operators they require to be - defined, except the requirements that (a) the semantics of the operators - grouped in one concept should be consistent (e.g. effects of - evaluating of a += b and - a = a + b expressions should be the - same), and (b) that the return types of the operators should follow - semantics of return types of corresponding operators for built-in types - (e.g. operator< should return a type convertible - to bool, and T::operator-= should return type - convertible to T). Such "loose" requirements make operators - library applicable to broader set of target classes from different - domains, i.e. eventually more useful.

- -

Usage

- -

Two-Argument Template Forms

- -

General Considerations

- -

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<T, - U>, equality_comparable<T, U>, - equivalent<T, U>, and - partially_ordered<T, - U>) 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.

- -

Mixed Arithmetics

- -

Another application of the two-argument template forms is for mixed - arithmetics between a type T and a type U that - is convertible to T. In this case there are two ways where - the two-argument template forms are helpful: one is to provide the - respective signatures for operator overloading, the second is - performance.

- -

With respect to the operator overloading assume e.g. that - U is int, that T is an - user-defined unlimited integer type, and that double - operator-(double, const T&) exists. If one wants to compute - int - T and does not provide T operator-(int, const - T&), the compiler will consider double operator-(double, - const T&) to be a better match than T operator-(const - T&, const T&), which will probably be different from the - user's intention. To define a complete set of operator signatures, - additional 'left' forms of the two-argument template forms are provided - (subtractable2_left<T, - U>, dividable2_left<T, - U>, modable2_left<T, - U>) that define the signatures for non-commutative - operators where U appears on the left hand side - (operator-(const U&, const T&), - operator/(const U&, const T&), operator%(const - U&, const T&)).

- -

With respect to the performance observe that when one uses the single - type binary operator for mixed type arithmetics, the type U - argument has to be converted to type T. In practice, - however, there are often more efficient implementations of, say - T::operator-=(const U&) that avoid unnecessary - conversions from U to T. The two-argument - template forms of the arithmetic operator create additional operator - interfaces that use these more efficient implementations. There is, - however, no performance gain in the 'left' forms: they still need a - conversion from U to T and have an - implementation equivalent to the code that would be automatically created - by the compiler if it considered the single type binary operator to be - the best match.

- -

Base Class Chaining and Object Size

- -

Every operator class template, except the arithmetic examples and the iterator - helpers, has an additional, but optional, template type parameter - B. This parameter will be a publicly-derived base class of - the instantiated template. This means it must be a class type. It can be - used to avoid the bloating of object sizes that is commonly associated - with multiple-inheritance from several empty base classes (see the note for users of older versions for more - details). To provide support for a group of operators, use the - B parameter to chain operator templates into a single-base - class hierarchy, demostrated in the usage example. - The technique is also used by the composite operator templates to group - operator definitions. If a chain becomes too long for the compiler to - support, try replacing some of the operator templates with a single - grouped operator template that chains the old templates together; the - length limit only applies to the number of templates directly in the - chain, not those hidden in group templates.

- -

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.

- -

Separate, Explicit - Instantiation

- -

On some compilers (e.g. Borland, GCC) even single-inheritance - seems to cause an increase in object size in some cases. If you are not - defining a class 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 struct less_than_comparable<myclass>;
-    template struct equality_comparable<myclass>;
-    template struct incrementable<myclass>;
-    template struct decrementable<myclass>;
-    template struct addable<myclass,long>;
-    template struct subtractable<myclass,long>;
-
-
- -

Note that some operator templates cannot use this workaround and must - be a base class of their primary operand type. Those templates define - operators which must be member functions, and the workaround needs the - operators to be independent friend functions. The relevant templates - are:

- - - -

As Daniel Krügler pointed out, this technique violates 14.6.5/2 - and is thus non-portable. The reasoning is, that the operators injected - by the instantiation of e.g. - less_than_comparable<myclass> can not be found - by ADL according to the rules given by 3.4.2/2, since myclass is - not an associated class of - less_than_comparable<myclass>. - Thus only use this technique if all else fails.

- -

Requirement Portability

- -

Many compilers (e.g. MSVC 6.3, GCC 2.95.2) will not enforce the - requirements in the operator template tables unless the operations which - depend on them are actually used. This is not standard-conforming - behavior. In particular, although it would be convenient to derive all - your classes which need binary operators from the operators<> and operators2<> templates, regardless of - whether they implement all the requirements of those templates, this - shortcut is not portable. Even if this currently works with your - compiler, it may not work later.

- -

Example

- -

This example shows how some of the arithmetic - operator templates can be used with a geometric point class - (template).

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

Arithmetic Operators

- -

The arithmetic operator templates ease the task of creating a custom - numeric type. Given a core set of operators, the templates add related - operators to the numeric class. These operations are like the ones the - standard arithmetic types have, and may include comparisons, adding, - incrementing, logical and bitwise manipulations, etc. Further, - since most numeric types need more than one of these operators, some - templates are provided to combine several of the basic operator templates - in one declaration.

- -

The requirements for the types used to instantiate the simple operator - templates are specified in terms of expressions which must be valid and - the expression's return type. The composite operator templates only list - what other templates they use. The supplied operations and requirements - of the composite operator templates can be inferred from the operations - and requirements of the listed components.

- -

Simple Arithmetic Operators

- -

These templates are "simple" since they provide operators based on a - single operation the base type has to provide. They have an additional - optional template parameter B, which is not shown, for the - base class chaining technique.

- -

The primary operand type T needs to be of class type, - built-in types are not supported.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Simple Arithmetic Operator Template Classes -
- - - - - - - - - - - - - - -
- Key -
T: primary operand typeU: alternate operand type
t, t1: values of type - Tu: value of type U
-
TemplateSupplied OperationsRequirementsPropagates constexpr?
less_than_comparable<T>
- less_than_comparable1<T>
bool operator>(const T&, const T&)
- bool operator<=(const T&, const T&)
- bool operator>=(const T&, const T&)
t < t1.
- Return convertible to bool. See the Ordering Note.
Since C++11
- (except MSVC < v19.22)
less_than_comparable<T, - U>
- less_than_comparable2<T, U>
bool operator<=(const T&, const U&)
- bool operator>=(const T&, const U&)
- bool operator>(const U&, const T&)
- bool operator<(const U&, const T&)
- bool operator<=(const U&, const T&)
- bool operator>=(const U&, const T&)
t < u. t > u.
- Returns convertible to bool. See the Ordering Note.
Since C++11
- (except MSVC < v19.22)
equality_comparable<T>
- equality_comparable1<T>
bool operator!=(const T&, const T&)t == t1.
- Return convertible to bool.
Since C++11
- (except MSVC < v19.22)
equality_comparable<T, - U>
- equality_comparable2<T, U>
bool operator==(const U&, const T&)
- bool operator!=(const U&, const T&)
- bool operator!=(const T&, const U&)
t == u.
- Return convertible to bool.
Since C++11
- (except MSVC < v19.22)
addable<T>
- addable1<T>
T operator+(const T&, const T&)T temp(t); temp += t1.
- Return convertible to T. See the Symmetry Note.
No
addable<T, U>
- addable2<T, U>
T operator+(const T&, const U&)
- T operator+(const U&, const T& )
T temp(t); temp += u.
- Return convertible to T. See the Symmetry Note.
No
subtractable<T>
- subtractable1<T>
T operator-(const T&, const T&)T temp(t); temp -= t1.
- Return convertible to T. See the Symmetry Note.
No
subtractable<T, - U>
- subtractable2<T, U>
T operator-(const T&, const U&)T temp(t); temp -= u.
- Return convertible to T. See the Symmetry Note.
No
subtractable2_left<T, - U>T operator-(const U&, const T&)T temp(u); temp -= t.
- Return convertible to T.
No
multipliable<T>
- multipliable1<T>
T operator*(const T&, const T&)T temp(t); temp *= t1.
- Return convertible to T. See the Symmetry Note.
No
multipliable<T, - U>
- multipliable2<T, U>
T operator*(const T&, const U&)
- T operator*(const U&, const T&)
T temp(t); temp *= u.
- Return convertible to T. See the Symmetry Note.
No
dividable<T>
- dividable1<T>
T operator/(const T&, const T&)T temp(t); temp /= t1.
- Return convertible to T. See the Symmetry Note.
No
dividable<T, U>
- dividable2<T, U>
T operator/(const T&, const U&)T temp(t); temp /= u.
- Return convertible to T. See the Symmetry Note.
No
dividable2_left<T, - U>T operator/(const U&, const T&)T temp(u); temp /= t.
- Return convertible to T.
No
modable<T>
- modable1<T>
T operator%(const T&, const T&)T temp(t); temp %= t1.
- Return convertible to T. See the Symmetry Note.
No
modable<T, U>
- modable2<T, U>
T operator%(const T&, const U&)T temp(t); temp %= u.
- Return convertible to T. See the Symmetry Note.
No
modable2_left<T, - U>T operator%(const U&, const T&)T temp(u); temp %= t.
- Return convertible to T.
No
orable<T>
- orable1<T>
T operator|(const T&, const T&)T temp(t); temp |= t1.
- Return convertible to T. See the Symmetry Note.
No
orable<T, U>
- orable2<T, U>
T operator|(const T&, const U&)
- T operator|(const U&, const T&)
T temp(t); temp |= u.
- Return convertible to T. See the Symmetry Note.
No
andable<T>
- andable1<T>
T operator&(const T&, const T&)T temp(t); temp &= t1.
- Return convertible to T. See the Symmetry Note.
No
andable<T, U>
- andable2<T, U>
T operator&(const T&, const U&)
- T operator&(const U&, const T&)
T temp(t); temp &= u.
- Return convertible to T. See the Symmetry Note.
No
xorable<T>
- xorable1<T>
T operator^(const T&, const T&)T temp(t); temp ^= t1.
- Return convertible to T. See the Symmetry Note.
No
xorable<T, U>
- xorable2<T, U>
T operator^(const T&, const U&)
- T operator^(const U&, const T&)
T temp(t); temp ^= u.
- Return convertible to T. See the Symmetry Note.
No
incrementable<T>T operator++(T&, int)T temp(t); ++t
- Return convertible to T.
No
decrementable<T>T operator--(T&, int)T temp(t); --t;
- Return convertible to T.
No
left_shiftable<T>
- left_shiftable1<T>
T operator<<(const T&, const T&)T temp(t); temp <<= t1.
- Return convertible to T. See the Symmetry Note.
No
left_shiftable<T, - U>
- left_shiftable2<T, U>
T operator<<(const T&, const U&)T temp(t); temp <<= u.
- Return convertible to T. See the Symmetry Note.
No
right_shiftable<T>
- right_shiftable1<T>
T operator>>(const T&, const T&)T temp(t); temp >>= t1.
- Return convertible to T. See the Symmetry Note.
No
right_shiftable<T, - U>
- right_shiftable2<T, U>
T operator>>(const T&, const U&)T temp(t); temp >>= u.
- Return convertible to T. See the Symmetry Note.
No
equivalent<T>
- equivalent1<T>
bool operator==(const T&, const T&)t < t1.
- Return convertible to bool. See the Ordering Note.
Since C++11
- (except MSVC < v19.22)
equivalent<T, U>
- equivalent2<T, U>
bool operator==(const T&, const U&)t < u. t > u.
- Returns convertible to bool. See the Ordering Note.
Since C++11
- (except MSVC < v19.22)
partially_ordered<T>
- partially_ordered1<T>
bool operator>(const T&, const T&)
- bool operator<=(const T&, const T&)
- bool operator>=(const T&, const T&)
t < t1. t == t1.
- Returns convertible to bool. See the Ordering Note.
Since C++11
- (except MSVC < v19.22)
partially_ordered<T, - U>
- partially_ordered2<T, U>
bool operator<=(const T&, const U&)
- bool operator>=(const T&, const U&)
- bool operator>(const U&, const T&)
- bool operator<(const U&, const T&)
- bool operator<=(const U&, const T&)
- bool operator>=(const U&, const T&)
t < u. t > u. t == - u.
- Returns convertible to bool. See the Ordering Note.
Since C++11
- (except MSVC < v19.22)
- -

Ordering Note

- -

The less_than_comparable<T> and - partially_ordered<T> - templates provide the same set of operations. However, the workings of - less_than_comparable<T> assume - that all values of type T can be placed in a total order. If - that is not true (e.g. Not-a-Number values in IEEE floating point - arithmetic), then partially_ordered<T> should be - used. The partially_ordered<T> template can - be used for a totally-ordered type, but it is not as efficient as - less_than_comparable<T>. This - rule also applies for less_than_comparable<T, U> and - partially_ordered<T, - U> with respect to the ordering of all T and - U values, and for both versions of equivalent<>. The solution for equivalent<> is to write a custom - operator== for the target class.

- -

Symmetry Note

- -

Before talking about symmetry, we need to talk about optimizations to - understand the reasons for the different implementation styles of - operators. Let's have a look at operator+ for a class - T as an example:

-
-T operator+( const T& lhs, const T& rhs )
-{
-   return T( lhs ) += rhs;
-}
-
- This would be a normal implementation of operator+, but it - is not an efficient one. An unnamed local copy of lhs is - created, operator+= is called on it and it is copied to the - function return value (which is another unnamed object of type - T). The standard doesn't generally allow the intermediate - object to be optimized away: - -
- 3.7.2/2: Automatic storage duration
-
- If a named automatic object has initialization or a destructor with - side effects, it shall not be destroyed before the end of its block, - nor shall it be eliminated as an optimization even if it appears to be - unused, except that a class object or its copy may be eliminated as - specified in 12.8. -
- The reference to 12.8 is important for us: - -
- 12.8/15: Copying class objects
- ...
- For a function with a class return type, if the expression in the - return statement is the name of a local object, and the cv-unqualified - type of the local object is the same as the function return type, an - implementation is permitted to omit creating the temporary object to - hold the function return value, even if the class copy constructor or - destructor has side effects. -
- This optimization is known as the named return value optimization (NRVO), - which leads us to the following implementation for - operator+: -
-T operator+( const T& lhs, const T& rhs )
-{
-   T nrv( lhs );
-   nrv += rhs;
-   return nrv;
-}
-
- Given this implementation, the compiler is allowed to remove the - intermediate object. Sadly, not all compiler implement the NRVO, some - even implement it in an incorrect way which makes it useless here. - Without the NRVO, the NRVO-friendly code is no worse than the original - code showed above, but there is another possible implementation, which - has some very special properties: -
-T operator+( T lhs, const T& rhs )
-{
-   return lhs += rhs;
-}
-
- The difference to the first implementation is that lhs is - not taken as a constant reference used to create a copy; instead, - lhs is a by-value parameter, thus it is already the copy - needed. This allows another optimization (12.2/2) for some cases. - Consider a + b + c where the result of - a + b is not copied when used as lhs - when adding c. This is more efficient than the original - code, but not as efficient as a compiler using the NRVO. For most people, - it is still preferable for compilers that don't implement the NRVO, but - the operator+ now has a different function signature. Also, - the number of objects created differs for - (a + b ) + c and - a + ( b + c ). Most probably, - this won't be a problem for you, but if your code relies on the function - signature or a strict symmetric behaviour, you should set - BOOST_FORCE_SYMMETRIC_OPERATORS in your user-config. This - will force the NRVO-friendly implementation to be used even for compilers - that don't implement the NRVO.
-
- -

Grouped Arithmetic Operators

- -

The following templates provide common groups of related operations. - For example, since a type which is addable is usually also subractable, - the additive template provides the - combined operators of both. The grouped operator templates have an - additional optional template parameter B, which is not - shown, for the base class chaining technique.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Grouped Arithmetic Operator Template Classes -
- - - - - - - - -
- Key -
T: primary operand typeU: alternate operand type
-
TemplateComponent Operator Templates
totally_ordered<T>
- totally_ordered1<T>
- -
totally_ordered<T, - U>
- totally_ordered2<T, U>
- -
additive<T>
- additive1<T>
- -
additive<T, U>
- additive2<T, U>
- -
multiplicative<T>
- multiplicative1<T>
- -
multiplicative<T, - U>
- multiplicative2<T, U>
- -
integer_multiplicative<T>
- - integer_multiplicative1<T>
- -
integer_multiplicative<T, - U>
- integer_multiplicative2<T, U>
- -
arithmetic<T>
- arithmetic1<T>
- -
arithmetic<T, U>
- arithmetic2<T, U>
- -
integer_arithmetic<T>
- integer_arithmetic1<T>
- -
integer_arithmetic<T, - U>
- integer_arithmetic2<T, U>
- -
bitwise<T>
- bitwise1<T>
- -
bitwise<T, U>
- bitwise2<T, U>
- -
unit_steppable<T> - -
shiftable<T>
- shiftable1<T>
- -
shiftable<T, U>
- shiftable2<T, U>
- -
ring_operators<T>
- ring_operators1<T>
- -
ring_operators<T, - U>
- ring_operators2<T, U>
- -
ordered_ring_operators<T>
- - ordered_ring_operators1<T>
- -
ordered_ring_operators<T, - U>
- ordered_ring_operators2<T, U>
- -
field_operators<T>
- field_operators1<T>
- -
field_operators<T, - U>
- field_operators2<T, U>
- -
ordered_field_operators<T>
- - ordered_field_operators1<T>
- -
ordered_field_operators<T, - U>
- ordered_field_operators2<T, U>
- -
euclidean_ring_operators<T>
- - euclidean_ring_operators1<T>
- -
euclidean_ring_operators<T, - U>
- euclidean_ring_operators2<T, U>
- -
ordered_euclidean_ring_operators<T>
- - ordered_euclidean_ring_operators1<T>
- -
ordered_euclidean_ring_operators<T, - U>
- ordered_euclidean_ring_operators2<T, U>
- -
- -

Spelling: euclidean vs. euclidian

- -

Older versions of the Boost.Operators library used - "euclidian", but it was pointed out that - "euclidean" is the more common spelling. - To be compatible with older version, the library now supports - both spellings. -

- -

Example Templates

- -

The arithmetic operator class templates operators<> and operators2<> are examples of - non-extensible operator grouping classes. These legacy class templates, - from previous versions of the header, cannot be used for base class chaining.

- - - - - - - - - - - - - - - - - - - - - - - - - -
- Final Arithmetic Operator Template Classes -
- - - - - - - - -
- Key -
T: primary operand typeU: alternate operand type
-
TemplateComponent Operator Templates
operators<T> - -
operators<T, U>
- operators2<T, U>
- -
- -

Arithmetic Operators Demonstration and Test - Program

- -

The operators_test.cpp - program demonstrates the use of the arithmetic operator templates, and - can also be used to verify correct operation. Check the compiler status - report for the test results with selected platforms.

- -

Dereference Operators and Iterator Helpers

- -

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

- -

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

- -

The requirements for the types used to instantiate the dereference - operators are specified in terms of expressions which must be valid and - their return type. The composite operator templates list their component - templates, which the instantiating type must support, and possibly other - requirements.

- -

Dereference Operators

- -

All the dereference operator templates in this table accept an - optional template parameter (not shown) to be used for base class chaining.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Dereference Operator Template Classes -
- - - - - - - - - - - - - - - - - - - - -
- Key -
T: operand typeP: pointer type
D: difference_typeR: reference type
i: object of type T (an - iterator)n: object of type D (an - index)
-
TemplateSupplied OperationsRequirements
dereferenceable<T, - P>P operator->() const*i. Address of the returned value convertible - to P.
indexable<T, D, - R>R operator[](D n) const*(i + n). Return of type - R.
- -

Grouped Iterator Operators

- -

There are five iterator operator class templates, each for a different - category of iterator. The following table shows the operator groups for - any category that a custom iterator could define. These class templates - have an additional optional template parameter B, which is - not shown, to support base class chaining.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Iterator Operator Class Templates -
- - - - - - - - - - - - - - - - - - - - -
- Key -
T: operand typeP: pointer type
D: difference_typeR: reference type
V: value_type -
-
TemplateComponent Operator Templates
input_iteratable<T, - P> - -
output_iteratable<T> - -
forward_iteratable<T, - P> - -
bidirectional_iteratable<T, - P> - -
random_access_iteratable<T, P, D, - R> - -
- -

Iterator Helpers

- -

There are also five iterator helper class templates, each - corresponding to a different iterator category. These classes cannot be - used for base class chaining. The following - summaries show that these class templates supply both the iterator - operators from the iterator operator class - templates and the iterator typedef's required by the C++ standard - (iterator_category, value_type, - etc.).

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Iterator Helper Class Templates -
- - - - - - - - - - - - - - - - - - - - -
- Key -
T: operand typeP: pointer type
D: difference_typeR: reference type
V: value_typex1, x2: objects of type T
-
TemplateOperations & Requirements
input_iterator_helper<T, - V, D, P, R> - Supports the operations and has the requirements of - - -
output_iterator_helper<T> - Supports the operations and has the requirements of - - - See also [1], [2]. -
forward_iterator_helper<T, V, D, P, - R> - Supports the operations and has the requirements of - - -
bidirectional_iterator_helper<T, - V, D, P, R> - Supports the operations and has the requirements of - - -
random_access_iterator_helper<T, - V, D, P, R> - Supports the operations and has the requirements of - - - To satisfy RandomAccessIterator, - x1 - x2 with return convertible to D is - also required. -
- -

Iterator Helper Notes

- -

[1] Unlike other iterator helpers templates, - output_iterator_helper takes only one template parameter - - the type of its target class. Although to some it might seem like an - unnecessary restriction, the standard requires - difference_type and value_type of any output - iterator to be void (24.3.1 [lib.iterator.traits]), and - output_iterator_helper template respects this requirement. - Also, output iterators in the standard have void pointer and - reference types, so the output_iterator_helper - does the same.

- -

[2] As self-proxying is the easiest and most common - way to implement output iterators (see, for example, insert [24.4.2] and - stream iterators [24.5] in the standard library), - output_iterator_helper supports the idiom by defining - operator* and operator++ member functions which - just return a non-const reference to the iterator itself. Support for - self-proxying allows us, in many cases, to reduce the task of writing an - output iterator to writing just two member functions - an appropriate - constructor and a copy-assignment operator. For example, here is a - possible implementation of boost::function_output_iterator - adaptor:

-
-template<class UnaryFunction>
-struct function_output_iterator
-    : boost::output_iterator_helper< function_output_iterator<UnaryFunction> >
-{
-    explicit function_output_iterator(UnaryFunction const& f = UnaryFunction())
-        : func(f) {}
-
-    template<typename T>
-    function_output_iterator& operator=(T const& value)
-    {
-        this->func(value);
-        return *this;
-    }
-
- private:
-    UnaryFunction func;
-};
-
- -

Note that support for self-proxying does not prevent you from using - output_iterator_helper to ease any other, different kind of - output iterator's implementation. If - output_iterator_helper's target type provides its own - definition of operator* or/and operator++, then - these operators will get used and the ones supplied by - output_iterator_helper will never be instantiated.

- -

Iterator Demonstration and Test Program

- -

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

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

Check the compiler status - report for the test results with selected platforms.

-
- -

Contributors

- -
-
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. Also - contributed iterators_test.cpp.
- -
Aleksey - Gurtovoy
- -
Contributed the code to support base class - chaining while remaining backward-compatible with old versions of - the library.
- -
Beman Dawes
- -
Contributed operators_test.cpp.
- -
Daryle Walker
- -
Contributed classes for the shift operators, equivalence, partial - ordering, and arithmetic conversions. Added the grouped operator - classes. Added helper classes for input and output iterators.
- -
Helmut Zeisel
- -
Contributed the 'left' operators and added some grouped operator - classes.
- -
Daniel Frey
- -
Contributed the NRVO-friendly and symmetric implementation of - arithmetic operators.
- -
- -

Note for Users of Older Versions

- -

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

- -

Strictly speaking, it was not the library's fault--the language rules - allow the compiler to apply the empty base class optimization in that - situation. In principle an arbitrary number of empty base classes can be - allocated at the same offset, provided that none of them have a common - ancestor (see section 10.5 [class.derived] paragraph 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: 7 Aug 2008

- -

Copyright © Beman Dawes, David Abrahams, 1999-2001.

-

Copyright © Daniel Frey, 2002-2009.

-

Use, modification, and distribution is subject to the Boost Software - License, Version 1.0. (See accompanying file - LICENSE_1_0.txt or copy at - - www.boost.org/LICENSE_1_0.txt)

- + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/utility/utilities/operators.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
+ - diff --git a/throw_exception.html b/throw_exception.html index 141f487..e6b6b29 100644 --- a/throw_exception.html +++ b/throw_exception.html @@ -1,15 +1,15 @@ - -Automatic redirection + + Automatic redirection Automatic redirection failed, please go to -throw_exception.html
-

© Copyright Beman Dawes, 2001

-

Distributed under the Boost Software License, Version 1.0. (See accompanying -file LICENSE_1_0.txt or copy -at www.boost.org/LICENSE_1_0.txt)

+../throw_exception/doc/html/throw_exception.html#using_boost_throw_exception
+

Copyright © Beman Dawes, 2001

+

Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy + at www.boost.org/LICENSE_1_0.txt)

diff --git a/utility.htm b/utility.htm index 711b58c..7569b21 100644 --- a/utility.htm +++ b/utility.htm @@ -1,583 +1,19 @@ - - - Header boost/utility.hpp Documentation - - -

boost.png (6897 bytes)Header - boost/utility.hpp

-

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

-

Contents

- -

- -

Class template - result_of

The class template - result_of helps determine the type of a - call expression. For example, given an lvalue f of - type F and lvalues t1, - t2, ..., tN of - types T1, T2, ..., - TN, respectively, the type - result_of<F(T1, T2, ..., - TN)>::type defines the result type - of the expression f(t1, t2, - ...,tN). This implementation permits - the type F to be a function pointer, - function reference, member function pointer, or class - type. By default, N may be any value between 0 and - 16. To change the upper limit, define the macro - BOOST_RESULT_OF_NUM_ARGS to the maximum - value for N. Class template result_of - resides in the header <boost/utility/result_of.hpp>.

- -

If your compiler's support for decltype is - adequate, result_of automatically uses it to - deduce the type of the call expression, in which case - result_of<F(T1, T2, ..., - TN)>::type names the type - decltype(boost::declval<F>()(boost::declval<T1>(), - boost::declval<T2>(), ..., - boost::declval<TN>())), as in the - following example.

- -
-
struct functor {
-    template<class T>
-    T operator()(T x)
-    {
-        return x;
-    }
-};
-
-typedef boost::result_of<
-    functor(int)
->::type type; // type is int
-
- -

You can test whether result_of is using - decltype by checking if the macro - BOOST_RESULT_OF_USE_DECLTYPE is defined after - including result_of.hpp. You can also force - result_of to use decltype by - defining BOOST_RESULT_OF_USE_DECLTYPE prior - to including result_of.hpp.

- -

If decltype is not used, - then automatic result type deduction of function - objects is not possible. Instead, result_of - uses the following protocol to allow the programmer to - specify a type. When F is a class type with a - member type result_type, - result_of<F(T1, T2, ..., - TN)>::type is - F::result_type. When F does - not contain result_type, - result_of<F(T1, T2, ..., - TN)>::type is F::result<F(T1, - T2, ..., TN)>::type when - N > 0 or void - when N = 0. Note that it is the - responsibility of the programmer to ensure that - function objects accurately advertise their result - type via this protocol, as in the following - example.

- -
-
struct functor {
-    template<class> struct result;
-
-    template<class F, class T>
-    struct result<F(T)> {
-        typedef T type;
-    };
-
-    template<class T>
-    T operator()(T x)
-    {
-        return x;
-    }
-};
-
-typedef boost::result_of<
-    functor(int)
->::type type; // type is int
-
- -

Since decltype is a new language - feature recently standardized in C++11, - if you are writing a function object - to be used with result_of, for - maximum portability, you might consider following - the above protocol even if your compiler has - proper decltype support. If you wish to continue to - use the protocol on compilers that - support decltype, there are two options: - You can use boost::tr1_result_of, which is also - defined in <boost/utility/result_of.hpp>. - Alternatively, you can define the macro - BOOST_RESULT_OF_USE_TR1, which causes - result_of to use the protocol described - above instead of decltype. If you choose to - follow the protocol, take care to ensure that the - result_type and - result<> members accurately - represent the return type of - operator() given a call expression.

- -

Additionally, boost::result_of - provides a third mode of operation, which some users - may find convenient. When - BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK - is defined, boost::result_of behaves as - follows. If the function object has a member - type result_type or member - template result<>, then - boost::result_of will use the TR1 - protocol. Otherwise, - boost::result_of will - use decltype. Using TR1 with - a declytpe fallback may workaround - certain problems at the cost of portability. For - example: -

    -
  • Deficient compiler: If your code - requires boost::result_of to work - with incomplete return types but your - compiler's decltype implementation - does not support incomplete return types, then you - can use the TR1 protocol as a workaround. Support - for incomplete return types was added late in the - C++11 standardization process - (see N3276) - and is not implemented by some compilers.
  • - -
  • Deficient legacy code: If your existing TR1 - function object advertises a different type than - the actual result type deduced - by decltype, then using TR1 with a - decltype fallback will allow you to - work with both your existing TR1 function objects - and new C++11 function object. This situation - could occur if your legacy function objects - misused the TR1 protocol. See the documentation on - known differences - between boost::result_of and TR1.
  • -
- - -

This implementation of result_of - requires class template partial specialization, the - ability to parse function types properly, and support - for SFINAE. If result_of is not supported - by your compiler, including the header - boost/utility/result_of.hpp will - define the macro BOOST_NO_RESULT_OF.

- -

For additional information - about result_of, see the C++ Library - Technical Report, - N1836, - or, for motivation and design rationale, - the result_of proposal.

- - -

Usage guidelines for boost::result_of

-
- -

The following are general suggestions about when - and how to use boost::result_of.

- -
    -
  1. If you are targeting C++11 and are not concerned - about portability to non-compliant compilers or - previous versions of the standard, then use - std::result_of. If std::result_of - meets your needs, then there's no reason to stop using - it.
  2. - -
  3. If you are targeting C++11 but may port your code - to legacy compilers at some time in the future, then - use boost::result_of with - decltype. When decltype is - used boost::result_of - and std::result_of are usually - interchangeable. See the documentation on - known differences - between boost::result_of and C++11 result_of.
  4. - -
  5. If compiler portability is required, - use boost::result_of with the TR1 protocol.
  6. -
- -

Regardless of how you - configure boost::result_of, it is - important to bear in mind that the return type of a - function may change depending on its arguments, and - additionally, the return type of a member function may - change depending on the cv-qualification of the - object. boost::result_of must be passed - the appropriately cv-qualified types in order to - deduce the corresponding return type. For example: - -

-
struct functor {
-    int& operator()(int);
-    int const& operator()(int) const;
-
-    float& operator()(float&);
-    float const& operator()(float const&);
-};
-
-typedef boost::result_of<
-    functor(int)
->::type type1; // type1 is int &
-
-typedef boost::result_of<
-    const functor(int)
->::type type2; // type2 is int const &
-
-typedef boost::result_of<
-    functor(float&)
->::type type3; // type3 is float &
-
-typedef boost::result_of<
-    functor(float const&)
->::type type4; // type4 is float const &
-
- - -

Usage guidelines for the TR1 result_of protocol

-
- -

On compliant C++11 - compilers, boost::result_of can - use decltype to deduce the type of any - call expression, including calls to function - objects. However, on pre-C++11 compilers or on - compilers without adequate decltype support, - additional scaffolding is needed from function - objects as described above. The following are - suggestions about how to use the TR1 protocol.

- -
    -
  • When the return type does not depend on the - argument types or the cv-qualification of the - function object, simply - define result_type. There is no need - to use the result template unless the - return type varies.
  • - -
  • Use the protocol specified type when defining - function prototypes. This can help ensure the - actual return type does not get out of sync with - the protocol specification. For example: - -
    -
    struct functor {
    -    typedef int result_type;
    -    result_type operator()(int);
    -};
    -
  • - -
  • Always specify the result - specialization near the corresponding - operator() overload. This can make it - easier to keep the specializations in sync with the - overloads. For example: - -
    -
    struct functor {
    -    template<class> struct result;
    -
    -    template<class F>
    -    struct result<F(int)> {
    -        typedef int& type;
    -    };
    -    result<functor(int)>::type operator()(int);
    -
    -    template<class F>
    -    struct result<const F(int)> {
    -        typedef int const& type;
    -    };
    -    result<const functor(int)>::type operator()(int) const;
    -};
    -
  • - -
  • Use type transformations to simplify - the result template specialization. For - example, the following uses - Boost.TypeTraits - to specialize the result template for - a single operator() that can be called on - both a const and non-const function object with - either an lvalue or rvalue argument. - -
    -
    struct functor {
    -    template<class> struct result;
    -
    -    template<class F, class T>
    -    struct result<F(T)> 
    -        : boost::remove_cv<
    -              typename boost::remove_reference<T>::type
    -          >
    -    {};
    -
    -    template<class T>
    -    T operator()(T const& x) const;
    -};
    -
  • -
- - -

Known differences between boost::result_of and TR1 result_of

-
- - When using decltype, boost::result_of - ignores the TR1 protocol and instead deduces the - return type of function objects directly - via decltype. In most situations, users - will not notice a difference, so long as they use the - protocol correctly. The following are situations in - which the type deduced - by boost::result_of is known to differ depending on - whether decltype or the TR1 protocol is - used. - -
    -
  • TR1 protocol misusage - -

    When using the TR1 - protocol, boost::result_of cannot - detect whether the actual type of a call to a - function object is the same as the type specified - by the protocol, which allows for the possibility - of inadvertent mismatches between the specified - type and the actual type. When - using decltype, these subtle bugs - may result in compilation errors. For example:

    - -
    -
    struct functor {
    -   typedef short result_type;
    -   int operator()(short);
    -};
    -
    -#ifdef BOOST_RESULT_OF_USE_DECLTYPE
    -
    -BOOST_STATIC_ASSERT((
    -   boost::is_same<boost::result_of<functor(short)>::type, int>::value
    -)); 
    -
    -#else
    -
    -BOOST_STATIC_ASSERT((
    -   boost::is_same<boost::result_of<functor(short)>::type, short>::value
    -));
    -
    -#endif
    -
    - -

    Note that the user can - force boost::result_of to use the TR1 - protocol even on platforms that - support decltype by - defining BOOST_RESULT_OF_USE_TR1.

  • - -
  • Nullary function objects - -

    When using the TR1 protocol, boost::result_of - cannot always deduce the type of calls to - nullary function objects, in which case the - type defaults to void. When using decltype, - boost::result_of always gives the actual type of the - call expression. For example:

    - -
    -
    struct functor {
    -   template<class> struct result {
    -       typedef int type;
    -   };
    -   int operator()();
    -};
    -
    -#ifdef BOOST_RESULT_OF_USE_DECLTYPE
    -
    -BOOST_STATIC_ASSERT((
    -   boost::is_same<boost::result_of<functor()>::type, int>::value
    -));
    -
    -#else
    -
    -BOOST_STATIC_ASSERT((
    -   boost::is_same<boost::result_of<functor()>::type, void>::value
    -));
    -
    -#endif
    -
    - -

    Note that there are some workarounds for the - nullary function problem. So long as the return - type does not vary, - result_type can always be used to - specify the return type regardless of arity. If the - return type does vary, then the user can - specialize boost::result_of itself for - nullary calls.

  • - -
  • Non-class prvalues and cv-qualification - -

    When using the TR1 - protocol, boost::result_of will - report the cv-qualified type specified - by result_type or - the result template regardless of - the actual cv-qualification of the call - expression. When using - decltype, boost::result_of - will report the actual type of the call expression, - which is not cv-qualified when the expression is a - non-class prvalue. For example:

    - -
    -
    struct functor {
    -   template<class> struct result;
    -   template<class F, class T> struct result<F(const T)> {
    -       typedef const T type;
    -   };
    -
    -   const short operator()(const short);
    -   int const & operator()(int const &);
    -};
    -
    -// Non-prvalue call expressions work the same with or without decltype.
    -
    -BOOST_STATIC_ASSERT((
    -   boost::is_same<
    -       boost::result_of<functor(int const &)>::type,
    -       int const &
    -::value
    -));
    -
    -// Non-class prvalue call expressions are not actually cv-qualified,
    -// but only the decltype-based result_of reports this accurately.
    -
    -#ifdef BOOST_RESULT_OF_USE_DECLTYPE
    -
    -BOOST_STATIC_ASSERT((
    -   boost::is_same<
    -       boost::result_of<functor(const short)>::type,
    -       short
    -::value
    -));
    -
    -#else
    -
    -BOOST_STATIC_ASSERT((
    -   boost::is_same<
    -       boost::result_of<functor(const short)>::type,
    -       const short
    -::value
    -));
    -
    -#endif
    -
  • -
- - -

Known differences between boost::result_of and C++11 result_of

-
- -

When using decltype, boost::result_of - implements most of the C++11 result_of - specification. One known exception is that - boost::result_of does not implement the - requirements regarding pointers to member data.

- -

Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others

- -

Macro BOOST_BINARY

- -

The macro BOOST_BINARY is used for the - representation of binary literals. It takes as an argument - a binary number arranged as an arbitrary amount of 1s and 0s in - groupings of length 1 to 8, with groups separated - by spaces. The type of the literal yielded is determined by - the same rules as those of hex and octal - literals (2.13.1p1). By implementation, this macro - expands directly to an octal literal during preprocessing, so - there is no overhead at runtime and the result is useable in - any place that an octal literal would be.

- -

In order to directly support binary literals with suffixes, - additional macros of the form BOOST_BINARY_XXX are also - provided, where XXX is a standard integer suffix in all capital - letters. In addition, LL and ULL suffixes may be used for representing - long long and unsigned long long types in compilers which provide - them as an extension.

- - -

The BOOST_BINARY family of macros resides in the header - <boost/utility/binary.hpp> - which is automatically included by - <boost/utility.hpp>. - -

Contributed by Matt Calabrese.

-

Example

-
-
-void foo( int );
-
-void foo( unsigned long );
-
-void bar()
-{
-  int value1 = BOOST_BINARY( 100 111000 01 1 110 );
-
-  unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned long
-
-  long long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported
-
-  assert(    BOOST_BINARY( 10010 )
-          &  BOOST_BINARY( 11000 )
-          == BOOST_BINARY( 10000 )
-        );
-
-  foo( BOOST_BINARY( 1010 ) ); // calls the first foo
-
-  foo( BOOST_BINARY_LU( 1010 ) ); // calls the second foo
-}
-
-
-

Revised  04 September, 2008 -

-

© Copyright Beman Dawes 1999-2003.

-

Distributed under the Boost Software License, Version 1.0. See -www.boost.org/LICENSE_1_0.txt

- - + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+
+ diff --git a/value_init.htm b/value_init.htm index 3222f69..3eb979d 100644 --- a/value_init.htm +++ b/value_init.htm @@ -1,514 +1,19 @@ - - - value_initialized - + Boost.Utility + - - -

- Header <boost/utility/value_init.hpp> -

- -

Contents

- -
-
Rationale
-
Introduction
-
Details
-
- - - -
-
Types and objects
-
- - - Acknowledgements
-
- -
-

Rationale

- -

Constructing and initializing objects in a generic way is difficult in - C++. The problem is that there are several different rules that apply -for initialization. Depending on the type, the value of a newly constructed - object can be zero-initialized (logically 0), default-constructed (using - the default constructor), or indeterminate. When writing generic code, -this problem must be addressed. The template value_initialized provides -a solution with consistent syntax for value initialization of scalar, -union and class types. -Moreover, value_initialized offers a workaround to various -compiler issues regarding value-initialization. - -Furthermore, a const object, initialized_value is provided, -to avoid repeating the type name when retrieving the value from a -value_initialized<T> object. -
-

- -

Introduction

- -

-There are various ways to initialize a variable, in C++. The following -declarations all may have a local variable initialized to its default -value: -

-  T1 var1;
-  T2 var2 = 0;
-  T3 var3 = {};
-  T4 var4 = T4();
-
-Unfortunately, whether or not any of those declarations correctly -initialize the variable very much depends on its type. The first -declaration is valid for any -DefaultConstructible type (by definition). -However, it does not always do an initialization! -It correctly initializes the variable when it's an instance of a -class, and the author of the class has provided a proper default -constructor. On the other hand, the value of var1 is indeterminate when -its type is an arithmetic type, like int, float, or char. -An arithmetic variable -is of course initialized properly by the second declaration, T2 -var2 = 0. But this initialization form usually won't work for a -class type (unless the class was especially written to support being -initialized that way). The third form, T3 var3 = {} -initializes an aggregate, typically a "C-style" struct or a "C-style" array. -However, the syntax is not allowed for a class that has an explicitly declared -constructor. (But watch out for an upcoming C++ language change, -by Bjarne Stroustrup et al [1]!) -The fourth form is the most generic form of them, as it -can be used to initialize arithmetic types, class types, aggregates, pointers, and -other types. The declaration, T4 var4 = T4(), should be read -as follows: First a temporary object is created, by T4(). -This object is value-initialized. Next the temporary -object is copied to the named variable, var4. Afterwards, the temporary -is destroyed. While the copying and the destruction are likely to -be optimized away, C++ still requires the type T4 to be -CopyConstructible. -(So T4 needs to be both DefaultConstructible and CopyConstructible.) -A class may not be CopyConstructible, for example because it may have a -private and undefined copy constructor, -or because it may be derived from boost::noncopyable. -Scott Meyers [2] explains why a class would be defined like that. -

-

-There is another, less obvious disadvantage to the fourth form, T4 var4 = T4(): -It suffers from various compiler issues, causing -a variable to be left uninitialized in some compiler specific cases. -

-

-The template value_initialized -offers a generic way to initialize -an object, like T4 var4 = T4(), but without requiring its type -to be CopyConstructible. And it offers a workaround to those compiler issues -regarding value-initialization as well! It allows getting an initialized -variable of any type; it only requires the type to be DefaultConstructible. -A properly value-initialized object of type T is -constructed by the following declaration: -

-  value_initialized<T> var;
-
-

-

-The template initialized -offers both value-initialization and direct-initialization. -It is especially useful as a data member type, allowing the very same object -to be either direct-initialized or value-initialized. -

-

-The const object initialized_value -allows value-initializing a variable as follows: -

-  T var = initialized_value ;
-
-This form of initialization is semantically equivalent to T4 var4 = T4(), -but robust against the aforementioned compiler issues. - -

- -

Details

-

The C++ standard [3] contains the definitions - of zero-initialization and default-initialization. - Informally, zero-initialization means that the object is given the initial - value 0 (converted to the type) and default-initialization means that - POD [4] types are zero-initialized, while non-POD class - types are initialized with their corresponding default constructors. A -declaration can contain an initializer, which specifies the -object's initial value. The initializer can be just '()', which states that -the object shall be value-initialized (but see below). However, if a declaration - has no initializer and it is of a non-const, non-static - POD type, the initial value is indeterminate: (see §8.5, [dcl.init], for the - accurate definitions).

- -
int x ; // no initializer. x value is indeterminate.
std::string s ; // no initializer, s is default-constructed.

int y = int() ;
// y is initialized using copy-initialization
// but the temporary uses an empty set of parentheses as the initializer,
// so it is default-constructed.
// A default constructed POD type is zero-initialized,
// therefore, y == 0.

void foo ( std::string ) ;
foo ( std::string() ) ;
// the temporary string is default constructed
// as indicated by the initializer ()
- -

value-initialization

- -

The first Technical - Corrigendum for the C++ Standard (TC1), whose draft was released to - the public in November 2001, introduced Core - Issue 178 (among many other issues, of course).

- -

That issue introduced the new concept of value-initialization - (it also fixed the wording for zero-initialization). Informally, value-initialization - is similar to default-initialization with the exception that in some cases - non-static data members and base class sub-objects are also value-initialized. - The difference is that an object that is value-initialized won't have -(or at least is less likely to have) indeterminate values for data members - and base class sub-objects; unlike the case of an object default constructed. - (see Core Issue 178 for a normative description).

- -

In order to specify value-initialization of an object we need to use the - empty-set initializer: ().

- -

As before, a declaration with no intializer specifies default-initialization, - and a declaration with a non-empty initializer specifies copy (=xxx) or - direct (xxx) initialization.

- -
template<class T> void eat(T);
int x ; // indeterminate initial value.
std::string s; // default-initialized.
eat ( int() ) ; // value-initialized
eat ( std::string() ) ; // value-initialized
- -

value-initialization syntax

- -

Value initialization is specified using (). However, the empty set of -parentheses is not permitted by the syntax of initializers because it is -parsed as the declaration of a function taking no arguments:

- -
int x() ; // declares function int(*)()
- -

Thus, the empty () must be put in some other initialization context.

- -

One alternative is to use copy-initialization syntax:

- -
int x = int() ;
- -

This works perfectly fine for POD types. But for non-POD class types, -copy-initialization searches for a suitable constructor, which could be, -for instance, the copy-constructor (it also searches for a suitable conversion -sequence but this doesn't apply in this context). For an arbitrary unknown -type, using this syntax may not have the value-initialization effect intended -because we don't know if a copy from a default constructed object is exactly -the same as a default constructed object, and the compiler is allowed (in -some cases), but never required to, optimize the copy away.

- -

One possible generic solution is to use value-initialization of a non static -data member:

- -
template<class T> 
struct W
{
// value-initialization of 'data' here.
W() : data() {}
T data ;
} ;
W<int> w ;
// w.data is value-initialized for any type.
- -

This is the solution as it was supplied by earlier versions of the -value_initialized<T> template - class. Unfortunately this approach suffered from various compiler issues.

- -

compiler issues

- -Various compilers haven't yet fully implemented value-initialization. -So when an object should be value-initialized (according to the C++ Standard), -it may in practice still be left uninitialized, because of those -compiler issues! It's hard to make a general statement on what those issues -are like, because they depend on the compiler you are using, its version number, -and the type of object you would like to have value-initialized. -All compilers we have tested so far support value-initialization for arithmetic types properly. -However, various compilers may leave some types of aggregates uninitialized, when they -should be value-initialized. Value-initialization of objects of a pointer-to-member type may also -go wrong on various compilers. -

-

-At the moment of writing, May 2010, the following reported issues regarding -value-initialization are still there in current compiler releases: -

-Note that all known GCC issues regarding value-initialization are -fixed with GCC version 4.4, including -GCC Bug 30111. -Clang also has completely implemented value-initialization, as far as we know, -now that Clang Bug 7139 is fixed. -

- -New versions of value_initialized -(Boost release version 1.35 or higher) -offer a workaround to these issues: value_initialized may now clear -its internal data, prior to constructing the object that it contains. It will do -so for those compilers that need to have such a workaround, based on the -compiler defect macro BOOST_NO_COMPLETE_VALUE_INITIALIZATION. -

- -

Types and objects

- -

template class value_initialized<T>

- -
namespace boost {

template<class T>
class value_initialized
{ -
public : -
value_initialized() : x() {} -
operator T const &() const { return x ; } -
operator T&() { return x ; } -
T const &data() const { return x ; } -
T& data() { return x ; } -
void swap( value_initialized& ); -
-
private : -
unspecified x ; -
} ; -
-
template<class T> -
T const& get ( value_initialized<T> const& x ) -
{ -
return x.data() ; -
} -
-
template<class T> -
T& get ( value_initialized<T>& x ) -
{ -
return x.data() ; -
} -
-
template<class T> -
void swap ( value_initialized<T>& lhs, value_initialized<T>& rhs ) -
{ -
lhs.swap(rhs) ; -
} -
-
} // namespace boost -
- -

An object of this template class is a T-wrapper convertible - to 'T&' whose wrapped object (data member of type T) - is value-initialized upon default-initialization - of this wrapper class:

- -
int zero = 0 ;
value_initialized<int> x ;
assert ( x == zero ) ;

std::string def ;
value_initialized< std::string > y ;
assert ( y == def ) ;
- -

The purpose of this wrapper is to provide a consistent syntax for value - initialization of scalar, union and class types (POD and non-POD) since - the correct syntax for value initialization varies (see value-initialization syntax)

- -

The wrapped object can be accessed either through the conversion operator - T&, the member function data(), or the -non-member function get():

- -
void watch(int);
value_initialized<int> x; -

watch(x) ; // operator T& used.
watch(x.data());
watch( get(x) ) // function get() used
- -

Both const and non-const objects can be wrapped. - Mutable objects can be modified directly from within the wrapper but constant - objects cannot:

- -

When T is a Swappable type, value_initialized<T> - is swappable as well, by calling its swap member function - as well as by calling boost::swap.

- -
value_initialized<int> x ; 
static_cast<int&>(x) = 1 ; // OK
get(x) = 1 ; // OK -

value_initialized<int const> y ;
static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&
static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value
get(y) = 1 ; // ERROR: cannot modify a const value
- -

Warning:

- -

The value_initialized implementation of Boost version 1.40.0 and older -allowed non-const access to the wrapped object, from a constant wrapper, -both by its conversion operator and its data() member function. For example:

- -
value_initialized<int> const x_c ;
int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const. -
xr = 2 ;
- -

The reason for this obscure behavior was that some compilers - didn't accept the following valid code:

- -
struct X
{
operator int&() ;
operator int const&() const ;
};
X x ;
(x == 1 ) ; // ERROR HERE!
- -

The current version of value_initialized no longer has this obscure behavior. -As compilers nowadays widely support overloading the conversion operator by having a const and a non-const version, we have decided to fix the issue accordingly. So the current version supports the idea of logical constness. -
-

- -

Recommended practice: The non-member get() idiom

- -

The obscure behavior of being able to modify a non-const -wrapped object from within a constant wrapper (as was supported by previous -versions of value_initialized) -can be avoided if access to -the wrapped object is always performed with the get() idiom:

- -
value_initialized<int> x ;
get(x) = 1 ; // OK

value_initialized<int const> cx ;
get(x) = 1 ; // ERROR: Cannot modify a const object

value_initialized<int> const x_c ;
get(x_c) = 1 ; // ERROR: Cannot modify a const object

value_initialized<int const> const cx_c ;
get(cx_c) = 1 ; // ERROR: Cannot modify a const object
- -

template class initialized<T>

- -
namespace boost {

template<class T>
class initialized
{ -
public : -
initialized() : x() {} -
explicit initialized(T const & arg) : x(arg) {} -
operator T const &() const; -
operator T&(); -
T const &data() const; -
T& data(); -
void swap( initialized& ); -
-
private : -
unspecified x ; -
} ; -
-
template<class T> -
T const& get ( initialized<T> const& x ); -
-
template<class T> -
T& get ( initialized<T>& x ); -
-
template<class T> -
void swap ( initialized<T>& lhs, initialized<T>& rhs ); -
-
} // namespace boost -
- -The template class boost::initialized<T> supports both value-initialization -and direct-initialization, so its interface is a superset of the interface -of value_initialized<T>: Its default-constructor -value-initializes the wrapped object just like the default-constructor of -value_initialized<T>, but boost::initialized<T> -also offers an extra explicit -constructor, which direct-initializes the wrapped object by the specified value. -

- -initialized<T> is especially useful when the wrapped -object must be either value-initialized or direct-initialized, depending on -runtime conditions. For example, initialized<T> could -hold the value of a data member that may be value-initialized by some -constructors, and direct-initialized by others. -On the other hand, if it is known beforehand that the -object must always be value-initialized, value_initialized<T> -may be preferable. And if the object must always be -direct-initialized, none of the two wrappers really needs to be used. -

- - -

initialized_value

- -
-namespace boost {
-class initialized_value_t
-{
-  public :
-    template <class T> operator T() const ;
-};
-
-initialized_value_t const initialized_value = {} ;
-
-} // namespace boost
-
- -initialized_value provides a convenient way to get -an initialized value: its conversion operator provides an appropriate -value-initialized object for any CopyConstructible type. - -Suppose you need to have an initialized variable of type T. -You could do it as follows: -
-  T var = T();
-
-But as mentioned before, this form suffers from various compiler issues. -The template value_initialized offers a workaround: -
-  T var = get( value_initialized<T>() );
-
-Unfortunately both forms repeat the type name, which -is rather short now (T), but could of course be -more like Namespace::Template<Arg>::Type. -Instead, one could use initialized_value as follows: -
-  T var = initialized_value ;
-
- -

References

- [1] Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote - various papers, proposing to extend the support for brace-enclosed initializer lists - in the next version of C++. - This would allow a variable var of any DefaultConstructible type - T to be value-initialized by doing T var = {}. - The papers are listed at Bjarne's web page, - My C++ Standards committee papers
- [2] Scott Meyers, Effective C++, Third Edition, item 6, - Explicitly disallow the use of compiler-generated functions you do not want, - Scott Meyers: Books and CDs
- [3] The C++ Standard, Second edition (2003), ISO/IEC 14882:2003
- [4] POD stands for "Plain Old Data" - -

Acknowledgements

- value_initialized was developed by Fernando Cacciola, with help and -suggestions from David Abrahams and Darin Adler.
-Special thanks to Björn Karlsson who carefully edited and completed this documentation. - -

value_initialized was reimplemented by Fernando Cacciola and Niels Dekker -for Boost release version 1.35 (2008), offering a workaround to various compiler issues. -

-

boost::initialized was very much inspired by feedback from Edward Diener and - Jeffrey Hellrung. -

-

initialized_value was written by Niels Dekker, and added to Boost release version 1.36 (2008). -

-

Developed by Fernando Cacciola, - the latest version of this file can be found at www.boost.org. -

- -
-

Revised 30 May 2010

- -

© Copyright Fernando Cacciola, 2002 - 2010.

- -

Distributed under the Boost Software License, Version 1.0. See -www.boost.org/LICENSE_1_0.txt

- -
-
- + +Automatic redirection failed, please go to +./doc/html/utility/utilities/value_init.html +
+ + Boost.Utility
+
+ Distributed under 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)
+
+