diff options
Diffstat (limited to 'src/boost/libs/utility')
56 files changed, 12154 insertions, 0 deletions
diff --git a/src/boost/libs/utility/Assignable.html b/src/boost/libs/utility/Assignable.html new file mode 100644 index 000000000..d3b315765 --- /dev/null +++ b/src/boost/libs/utility/Assignable.html @@ -0,0 +1,109 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + +<html> +<head> + <meta http-equiv="Content-Language" content="en-us"> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> + + <title>Assignable</title> +</head> + +<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink= +"#FF0000"> + <img src="../../boost.png" alt="C++ Boost" width="277" height= + "86"><br clear="none"> + + <h1>Assignable</h1> + + <h3>Description</h3> + + <p>A type is Assignable if it is possible to assign one object of the type + to another object of that type.</p> + + <h3>Notation</h3> + + <table summary=""> + <tr> + <td valign="top"><tt>T</tt></td> + + <td valign="top">is type that is a model of Assignable</td> + </tr> + + <tr> + <td valign="top"><tt>t</tt></td> + + <td valign="top">is an object of type <tt>T</tt></td> + </tr> + + <tr> + <td valign="top"><tt>u</tt></td> + + <td valign="top">is an object of type <tt>T</tt> or possibly <tt>const + T</tt></td> + </tr> + </table> + + <h3>Definitions</h3> + + <h3>Valid expressions</h3> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Return type</th> + + <th>Semantics</th> + </tr> + + <tr> + <td valign="top">Assignment</td> + + <td valign="top"><tt>t = u</tt></td> + + <td valign="top"><tt>T&</tt></td> + + <td valign="top"><tt>t</tt> is equivalent to <tt>u</tt></td> + </tr> + </table> + + <h3>Models</h3> + + <ul> + <li><tt>int</tt></li> + + <li><tt>std::pair</tt></li> + </ul> + + <h3>See also</h3> + + <p><a href= + "http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a> + and <a href="./CopyConstructible.html">CopyConstructible</a><br></p> + <hr> + + <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src= + "../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional" + height="31" width="88"></a></p> + + <p>Revised + <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p> + + <table summary=""> + <tr valign="top"> + <td nowrap><i>Copyright © 2000</i></td> + + <td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of + Notre Dame (<a href= + "mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td> + </tr> + </table> + + <p><i>Distributed under the Boost Software License, Version 1.0. (See + accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or + copy at <a href= + "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p> +</body> +</html> diff --git a/src/boost/libs/utility/CMakeLists.txt b/src/boost/libs/utility/CMakeLists.txt new file mode 100644 index 000000000..25177b0d6 --- /dev/null +++ b/src/boost/libs/utility/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright 2018 Peter Dimov +# Copyright 2018 Andrey Semashev +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt + +# Partial (add_subdirectory only) and experimental CMake support +# Subject to change; please do not rely on the contents of this file yet. + +cmake_minimum_required(VERSION 3.5) + +project(BoostUtility LANGUAGES CXX) + +add_library(boost_utility INTERFACE) +add_library(Boost::utility ALIAS boost_utility) + +target_include_directories(boost_utility INTERFACE include) + +target_link_libraries(boost_utility + INTERFACE + Boost::config + Boost::container_hash + Boost::core + Boost::preprocessor + Boost::static_assert + Boost::throw_exception + Boost::type_traits +) diff --git a/src/boost/libs/utility/Collection.html b/src/boost/libs/utility/Collection.html new file mode 100644 index 000000000..b92ddd6ee --- /dev/null +++ b/src/boost/libs/utility/Collection.html @@ -0,0 +1,534 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + +<html> +<head> + <meta http-equiv="Content-Language" content="en-us"> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> + + <title>Collection</title> +</head> + +<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink= +"#FF0000"> + <h1><img src="../../boost.png" alt="boost logo" width="277" align="middle" + height="86"><br> + Collection</h1> + + <h3>Description</h3> + + <p>A Collection is a <i>concept</i> similar to the STL <a href= + "http://www.sgi.com/tech/stl/Container.html">Container</a> 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:</p> + + <ul> + <li>It is not required to "own" its elements: the lifetime of an element + in a Collection does not have to match the lifetime of the Collection + object, though the lifetime of the element should cover the lifetime of + the Collection object.</li> + + <li>The semantics of copying a Collection object is not defined (it could + be a deep or shallow copy or not even support copying).</li> + + <li>The associated reference type of a Collection does not have to be a + real C++ reference.</li> + </ul>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. + + <h3>Associated types</h3> + + <table border summary=""> + <tr> + <td valign="top">Value type</td> + + <td valign="top"><tt>X::value_type</tt></td> + + <td valign="top">The type of the object stored in a Collection. If the + Collection is <i>mutable</i> then the value type must be <a href= + "http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>. Otherwise + the value type must be <a href= + "./CopyConstructible.html">CopyConstructible</a>.</td> + </tr> + + <tr> + <td valign="top">Iterator type</td> + + <td valign="top"><tt>X::iterator</tt></td> + + <td valign="top">The type of iterator used to iterate through a + Collection's elements. The iterator's value type is expected to be the + Collection's value type. A conversion from the iterator type to the + const iterator type must exist. The iterator type must be an <a href= + "http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.</td> + </tr> + + <tr> + <td valign="top">Const iterator type</td> + + <td valign="top"><tt>X::const_iterator</tt></td> + + <td valign="top">A type of iterator that may be used to examine, but + not to modify, a Collection's elements.</td> + </tr> + + <tr> + <td valign="top">Reference type</td> + + <td valign="top"><tt>X::reference</tt></td> + + <td valign="top">A type that behaves like a reference to the + Collection's value type. <a href="#n1">[1]</a></td> + </tr> + + <tr> + <td valign="top">Const reference type</td> + + <td valign="top"><tt>X::const_reference</tt></td> + + <td valign="top">A type that behaves like a const reference to the + Collection's value type.</td> + </tr> + + <tr> + <td valign="top">Pointer type</td> + + <td valign="top"><tt>X::pointer</tt></td> + + <td valign="top">A type that behaves as a pointer to the Collection's + value type.</td> + </tr> + + <tr> + <td valign="top">Distance type</td> + + <td valign="top"><tt>X::difference_type</tt></td> + + <td valign="top">A signed integral type used to represent the distance + between two of the Collection's iterators. This type must be the same + as the iterator's distance type.</td> + </tr> + + <tr> + <td valign="top">Size type</td> + + <td valign="top"><tt>X::size_type</tt></td> + + <td valign="top">An unsigned integral type that can represent any + nonnegative value of the Collection's distance type.</td> + </tr> + </table> + + <h3>Notation</h3> + + <table summary=""> + <tr> + <td valign="top"><tt>X</tt></td> + + <td valign="top">A type that is a model of Collection.</td> + </tr> + + <tr> + <td valign="top"><tt>a</tt>, <tt>b</tt></td> + + <td valign="top">Object of type <tt>X</tt>.</td> + </tr> + + <tr> + <td valign="top"><tt>T</tt></td> + + <td valign="top">The value type of <tt>X</tt>.</td> + </tr> + </table> + + <h3>Valid expressions</h3> + + <p>The following expressions must be valid.</p> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Return type</th> + </tr> + + <tr> + <td valign="top">Beginning of range</td> + + <td valign="top"><tt>a.begin()</tt></td> + + <td valign="top"><tt>iterator</tt> if <tt>a</tt> is mutable, + <tt>const_iterator</tt> otherwise</td> + </tr> + + <tr> + <td valign="top">End of range</td> + + <td valign="top"><tt>a.end()</tt></td> + + <td valign="top"><tt>iterator</tt> if <tt>a</tt> is mutable, + <tt>const_iterator</tt> otherwise</td> + </tr> + + <tr> + <td valign="top">Size</td> + + <td valign="top"><tt>a.size()</tt></td> + + <td valign="top"><tt>size_type</tt></td> + </tr><!-- +<TR> +<TD VAlign=top> +Maximum size +</TD> +<TD VAlign=top> +<tt>a.max_size()</tt> +</TD> +<TD VAlign=top> +<tt>size_type</tt> +</TD> +</TR> +--> + + <tr> + <td valign="top">Empty Collection</td> + + <td valign="top"><tt>a.empty()</tt></td> + + <td valign="top">Convertible to <tt>bool</tt></td> + </tr> + + <tr> + <td valign="top">Swap</td> + + <td valign="top"><tt>a.swap(b)</tt></td> + + <td valign="top"><tt>void</tt></td> + </tr> + </table> + + <h3>Expression semantics</h3> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Semantics</th> + + <th>Postcondition</th> + </tr> + + <tr> + <td valign="top">Beginning of range</td> + + <td valign="top"><tt>a.begin()</tt></td> + + <td valign="top">Returns an iterator pointing to the first element in + the Collection.</td> + + <td valign="top"><tt>a.begin()</tt> is either dereferenceable or + past-the-end. It is past-the-end if and only if <tt>a.size() == + 0</tt>.</td> + </tr> + + <tr> + <td valign="top">End of range</td> + + <td valign="top"><tt>a.end()</tt></td> + + <td valign="top">Returns an iterator pointing one past the last element + in the Collection.</td> + + <td valign="top"><tt>a.end()</tt> is past-the-end.</td> + </tr> + + <tr> + <td valign="top">Size</td> + + <td valign="top"><tt>a.size()</tt></td> + + <td valign="top">Returns the size of the Collection, that is, its + number of elements.</td> + + <td valign="top"><tt>a.size() >= 0</tt></td> + </tr><!-- +<TR> +<TD VAlign=top> +Maximum size +</TD> +<TD VAlign=top> +<tt>a.max_size()</tt> +</TD> +<TD VAlign=top> + +</TD> +<TD VAlign=top> +Returns the largest size that this Collection can ever have. <A href="#8">[8]</A> +</TD> +<TD VAlign=top> +<tt>a.max_size() >= 0 && a.max_size() >= a.size()</tt> +</TD> +</TR> + --> + + <tr> + <td valign="top">Empty Collection</td> + + <td valign="top"><tt>a.empty()</tt></td> + + <td valign="top">Equivalent to <tt>a.size() == 0</tt>. (But possibly + faster.)</td> + + <td valign="top"> </td> + </tr> + + <tr> + <td valign="top">Swap</td> + + <td valign="top"><tt>a.swap(b)</tt></td> + + <td valign="top">Equivalent to <tt>swap(a,b)</tt></td> + + <td valign="top"> </td> + </tr> + </table> + + <h3>Complexity guarantees</h3> + + <p><tt>begin()</tt> and <tt>end()</tt> are amortized constant time.</p> + + <p><tt>size()</tt> is at most linear in the Collection's size. + <tt>empty()</tt> is amortized constant time.</p> + + <p><tt>swap()</tt> is at most linear in the size of the two + collections.</p> + + <h3>Invariants</h3> + + <table border summary=""> + <tr> + <td valign="top">Valid range</td> + + <td valign="top">For any Collection <tt>a</tt>, <tt>[a.begin(), + a.end())</tt> is a valid range.</td> + </tr> + + <tr> + <td valign="top">Range size</td> + + <td valign="top"><tt>a.size()</tt> is equal to the distance from + <tt>a.begin()</tt> to <tt>a.end()</tt>.</td> + </tr> + + <tr> + <td valign="top">Completeness</td> + + <td valign="top">An algorithm that iterates through the range + <tt>[a.begin(), a.end())</tt> will pass through every element of + <tt>a</tt>.</td> + </tr> + </table> + + <h3>Models</h3> + + <ul> + <li><tt>array</tt></li> + + <li><tt>array_ptr</tt></li> + + <li><tt>vector<bool></tt></li> + </ul> + + <h3>Collection Refinements</h3> + + <p>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.</p> + + <h4>ForwardCollection</h4> + + <p>The elements are arranged in some order that does not change + spontaneously from one iteration to the next. As a result, a + ForwardCollection is <a href= + "http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a> + and <a href= + "http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a>. + 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 <tt>it1 == it2</tt> and <tt>it1</tt> is + dereferenceable then <tt>++it1 == ++it2</tt>. The ForwardCollection also + has a <tt>front()</tt> method.</p> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Return type</th> + + <th>Semantics</th> + </tr> + + <tr> + <td valign="top">Front</td> + + <td valign="top"><tt>a.front()</tt></td> + + <td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable,<br> + <tt>const_reference</tt> otherwise.</td> + + <td valign="top">Equivalent to <tt>*(a.begin())</tt>.</td> + </tr> + </table> + + <h4>ReversibleCollection</h4> + + <p>The container provides access to iterators that traverse in both + directions (forward and reverse). The iterator type must meet all of the + requirements of <a href= + "http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a> + except that the reference type does not have to be a real C++ reference. + The ReversibleCollection adds the following requirements to those of + ForwardCollection.</p> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Return type</th> + + <th>Semantics</th> + </tr> + + <tr> + <td valign="top">Beginning of range</td> + + <td valign="top"><tt>a.rbegin()</tt></td> + + <td valign="top"><tt>reverse_iterator</tt> if <tt>a</tt> is mutable, + <tt>const_reverse_iterator</tt> otherwise.</td> + + <td valign="top">Equivalent to + <tt>X::reverse_iterator(a.end())</tt>.</td> + </tr> + + <tr> + <td valign="top">End of range</td> + + <td valign="top"><tt>a.rend()</tt></td> + + <td valign="top"><tt>reverse_iterator</tt> if <tt>a</tt> is mutable, + <tt>const_reverse_iterator</tt> otherwise.</td> + + <td valign="top">Equivalent to + <tt>X::reverse_iterator(a.begin())</tt>.</td> + </tr> + + <tr> + <td valign="top">Back</td> + + <td valign="top"><tt>a.back()</tt></td> + + <td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable,<br> + <tt>const_reference</tt> otherwise.</td> + + <td valign="top">Equivalent to <tt>*(--a.end())</tt>.</td> + </tr> + </table> + + <h4>SequentialCollection</h4> + + <p>The elements are arranged in a strict linear order. No extra methods are + required.</p> + + <h4>RandomAccessCollection</h4> + + <p>The iterators of a RandomAccessCollection satisfy all of the + requirements of <a href= + "http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a> + except that the reference type does not have to be a real C++ reference. In + addition, a RandomAccessCollection provides an element access operator.</p> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Return type</th> + + <th>Semantics</th> + </tr> + + <tr> + <td valign="top">Element Access</td> + + <td valign="top"><tt>a[n]</tt></td> + + <td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable, + <tt>const_reference</tt> otherwise.</td> + + <td valign="top">Returns the nth element of the Collection. <tt>n</tt> + must be convertible to <tt>size_type</tt>. Precondition: <tt>0 <= n + < a.size()</tt>.</td> + </tr> + </table> + + <h3>Notes</h3> + + <p><a name="n1" id="n1">[1]</a> 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).</p> + + <h3>See also</h3> + + <p><a href= + "http://www.sgi.com/tech/stl/Container.html">Container</a><br></p> + <hr> + + <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src= + "../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional" + height="31" width="88"></a></p> + + <p>Revised + <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 + December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p> + + <table summary=""> + <tr valign="top"> + <td nowrap><i>Copyright © 2000</i></td> + + <td><i><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy + Siek</a>, Univ.of Notre Dame and C++ Library & Compiler Group/SGI + (<a href="mailto:jsiek@engr.sgi.com">jsiek@engr.sgi.com</a>)</i></td> + </tr> + </table> + + <p><i>Distributed under the Boost Software License, Version 1.0. (See + accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or + copy at <a href= + "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p> +</body> +</html> diff --git a/src/boost/libs/utility/CopyConstructible.html b/src/boost/libs/utility/CopyConstructible.html new file mode 100644 index 000000000..6a7ce6557 --- /dev/null +++ b/src/boost/libs/utility/CopyConstructible.html @@ -0,0 +1,185 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + +<html> +<head> + <meta http-equiv="Content-Language" content="en-us"> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> + + <title>Copy Constructible</title> +</head> + +<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink= +"#FF0000"> + <img src="../../boost.png" alt="C++ Boost" width="277" height= + "86"><br clear="none"> + + <h1>Copy Constructible</h1> + + <h3>Description</h3> + + <p>A type is Copy Constructible if it is possible to copy objects of that + type.</p> + + <h3>Notation</h3> + + <table summary=""> + <tr> + <td valign="top"><tt>T</tt></td> + + <td valign="top">is type that is a model of Copy Constructible</td> + </tr> + + <tr> + <td valign="top"><tt>t</tt></td> + + <td valign="top">is an object of type <tt>T</tt></td> + </tr> + + <tr> + <td valign="top"><tt>u</tt></td> + + <td valign="top">is an object of type <tt>const T</tt></td> + </tr> + </table> + + <h3>Definitions</h3> + + <h3>Valid expressions</h3> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Return type</th> + + <th>Semantics</th> + </tr> + + <tr> + <td valign="top">Copy constructor</td> + + <td valign="top"><tt>T(t)</tt></td> + + <td valign="top"><tt>T</tt></td> + + <td valign="top"><tt>t</tt> is equivalent to <tt>T(t)</tt></td> + </tr> + + <tr> + <td valign="top">Copy constructor</td> + + <td valign="top"> + <pre> +T(u) +</pre> + </td> + + <td valign="top"><tt>T</tt></td> + + <td valign="top"><tt>u</tt> is equivalent to <tt>T(u)</tt></td> + </tr> + + <tr> + <td valign="top">Destructor</td> + + <td valign="top"> + <pre> +t.~T() +</pre> + </td> + + <td valign="top"><tt>T</tt></td> + + <td valign="top"> </td> + </tr> + + <tr> + <td valign="top">Address Operator</td> + + <td valign="top"> + <pre> +&t +</pre> + </td> + + <td valign="top"><tt>T*</tt></td> + + <td valign="top">denotes the address of <tt>t</tt></td> + </tr> + + <tr> + <td valign="top">Address Operator</td> + + <td valign="top"> + <pre> +&u +</pre> + </td> + + <td valign="top"><tt>T*</tt></td> + + <td valign="top">denotes the address of <tt>u</tt></td> + </tr> + </table> + + <h3>Models</h3> + + <ul> + <li><tt>int</tt></li> + + <li><tt>std::pair</tt></li> + </ul> + + <h3>Concept Checking Class</h3> + <pre> + 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; + }; +</pre> + + <h3>See also</h3> + + <p><a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default + Constructible</a> and <a href="./Assignable.html">Assignable</a><br></p> + <hr> + + <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src= + "../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional" + height="31" width="88"></a></p> + + <p>Revised + <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 + December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p> + + <table summary=""> + <tr valign="top"> + <td nowrap><i>Copyright © 2000</i></td> + + <td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of + Notre Dame (<a href= + "mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td> + </tr> + </table> + + <p><i>Distributed under the Boost Software License, Version 1.0. (See + accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or + copy at <a href= + "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p> +</body> +</html> diff --git a/src/boost/libs/utility/LessThanComparable.html b/src/boost/libs/utility/LessThanComparable.html new file mode 100644 index 000000000..15b938fc5 --- /dev/null +++ b/src/boost/libs/utility/LessThanComparable.html @@ -0,0 +1,210 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + +<html> +<!-- + == Copyright (c) 1996-1999 + == Silicon Graphics Computer Systems, Inc. + == + == Permission to use, copy, modify, distribute and sell this software + == and its documentation for any purpose is hereby granted without fee, + == provided that the above copyright notice appears in all copies and + == that both that copyright notice and this permission notice appear + == in supporting documentation. Silicon Graphics makes no + == representations about the suitability of this software for any + == purpose. It is provided "as is" without express or implied warranty. + == + == Copyright (c) 1994 + == Hewlett-Packard Company + == + == Permission to use, copy, modify, distribute and sell this software + == and its documentation for any purpose is hereby granted without fee, + == provided that the above copyright notice appears in all copies and + == that both that copyright notice and this permission notice appear + == in supporting documentation. Hewlett-Packard Company makes no + == representations about the suitability of this software for any + == purpose. It is provided "as is" without express or implied warranty. + == + --> + +<head> + <meta http-equiv="Content-Language" content="en-us"> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> + + <title>LessThanComparable</title> +</head> + +<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink= +"#FF0000"> + <img src="../../boost.png" alt="C++ Boost" width="277" height= + "86"><br clear="none"> + + <h1>LessThanComparable</h1> + + <h3>Description</h3> + + <p>A type is LessThanComparable if it is ordered: it must be possible to + compare two objects of that type using <tt>operator<</tt>, and + <tt>operator<</tt> must be a strict weak ordering relation.</p> + + <h3>Refinement of</h3> + + <h3>Associated types</h3> + + <h3>Notation</h3> + + <table summary=""> + <tr> + <td valign="top"><tt>X</tt></td> + + <td valign="top">A type that is a model of LessThanComparable</td> + </tr> + + <tr> + <td valign="top"><tt>x</tt>, <tt>y</tt>, <tt>z</tt></td> + + <td valign="top">Object of type <tt>X</tt></td> + </tr> + </table> + + <h3>Definitions</h3> + + <p>Consider the relation <tt>!(x < y) && !(y < x)</tt>. If + this relation is transitive (that is, if <tt>!(x < y) && !(y + < x) && !(y < z) && !(z < y)</tt> implies <tt>!(x + < z) && !(z < x)</tt>), then it satisfies the mathematical + definition of an equivalence relation. In this case, <tt>operator<</tt> + is a <i>strict weak ordering</i>.</p> + + <p>If <tt>operator<</tt> is a strict weak ordering, and if each + equivalence class has only a single element, then <tt>operator<</tt> is + a <i>total ordering</i>.</p> + + <h3>Valid expressions</h3> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Type requirements</th> + + <th>Return type</th> + </tr> + + <tr> + <td valign="top">Less</td> + + <td valign="top"><tt>x < y</tt></td> + + <td valign="top"> </td> + + <td valign="top">Convertible to <tt>bool</tt></td> + </tr> + </table> + + <h3>Expression semantics</h3> + + <table border summary=""> + <tr> + <th>Name</th> + + <th>Expression</th> + + <th>Precondition</th> + + <th>Semantics</th> + + <th>Postcondition</th> + </tr> + + <tr> + <td valign="top">Less</td> + + <td valign="top"><tt>x < y</tt></td> + + <td valign="top"><tt>x</tt> and <tt>y</tt> are in the domain of + <tt><</tt></td> + + <td valign="top"> </td> + </tr> + </table> + + <h3>Complexity guarantees</h3> + + <h3>Invariants</h3> + + <table border summary=""> + <tr> + <td valign="top">Irreflexivity</td> + + <td valign="top"><tt>x < x</tt> must be false.</td> + </tr> + + <tr> + <td valign="top">Antisymmetry</td> + + <td valign="top"><tt>x < y</tt> implies !(y < x) <a href= + "#n2">[2]</a></td> + </tr> + + <tr> + <td valign="top">Transitivity</td> + + <td valign="top"><tt>x < y</tt> and <tt>y < z</tt> implies <tt>x + < z</tt> <a href="#n3">[3]</a></td> + </tr> + </table> + + <h3>Models</h3> + + <ul> + <li>int</li> + </ul> + + <h3>Notes</h3> + + <p><a name="n1" id="n1">[1]</a> Only <tt>operator<</tt> is fundamental; + the other inequality operators are essentially syntactic sugar.</p> + + <p><a name="n2" id="n2">[2]</a> Antisymmetry is a theorem, not an axiom: it + follows from irreflexivity and transitivity.</p> + + <p><a name="n3" id="n3">[3]</a> Because of irreflexivity and transitivity, + <tt>operator<</tt> always satisfies the definition of a <i>partial + ordering</i>. The definition of a <i>strict weak ordering</i> is stricter, + and the definition of a <i>total ordering</i> is stricter still.</p> + + <h3>See also</h3> + + <p><a href= + "http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>, + <a href= + "http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</a><br> + </p> + <hr> + + <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src= + "../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional" + height="31" width="88"></a></p> + + <p>Revised + <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 + December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p> + + <table summary=""> + <tr valign="top"> + <td nowrap><i>Copyright © 2000</i></td> + + <td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of + Notre Dame (<a href= + "mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td> + </tr> + </table> + + <p><i>Distributed under the Boost Software License, Version 1.0. (See + accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or + copy at <a href= + "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p> +</body> +</html> diff --git a/src/boost/libs/utility/MultiPassInputIterator.html b/src/boost/libs/utility/MultiPassInputIterator.html new file mode 100644 index 000000000..e331ca3aa --- /dev/null +++ b/src/boost/libs/utility/MultiPassInputIterator.html @@ -0,0 +1,95 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + +<html> +<head> + <meta http-equiv="Content-Language" content="en-us"> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> + + <title>MultiPassInputIterator</title> +</head> + +<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink= +"#FF0000"> + <img src="../../boost.png" alt="C++ Boost" width="277" height= + "86"><br clear="none"> + + <h2><a name="concept:MultiPassInputIterator" id= + "concept:MultiPassInputIterator"></a> Multi-Pass Input Iterator</h2> + + <p>This concept is a refinement of <a href= + "http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, adding + the requirements that the iterator can be used to make multiple passes + through a range, and that if <tt>it1 == it2</tt> and <tt>it1</tt> is + dereferenceable then <tt>++it1 == ++it2</tt>. The Multi-Pass Input Iterator + is very similar to the <a href= + "http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>. + The only difference is that a <a href= + "http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a> + requires the <tt>reference</tt> type to be <tt>value_type&</tt>, + whereas MultiPassInputIterator is like <a href= + "http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> in that + the <tt>reference</tt> type merely has to be convertible to + <tt>value_type</tt>.</p> + + <h3>Design Notes</h3> + + <p>comments by Valentin Bonnard:</p> + + <p>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.</p> + + <p>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.</p> + + <p>Other translations are:<br> + std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br> + std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue + Iterator<br> + std::Random Access Iterator -> Random Access Iterator & Lvalue + Iterator<br></p> + + <p>Note that in practice the only operation not allowed on my Forward + Iterator which is allowed on std::Forward Iterator is <tt>&*it</tt>. I + think that <tt>&*</tt> is rarely needed in generic code.</p> + + <p>reply by Jeremy Siek:</p> + + <p>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.<br></p> + <hr> + + <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src= + "../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional" + height="31" width="88"></a></p> + + <p>Revised + <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 + December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p> + + <table summary=""> + <tr valign="top"> + <td nowrap><i>Copyright © 2000</i></td> + + <td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of + Notre Dame (<a href= + "mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td> + </tr> + </table> + + <p><i>Distributed under the Boost Software License, Version 1.0. (See + accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or + copy at <a href= + "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p> +</body> +</html> diff --git a/src/boost/libs/utility/OptionalPointee.html b/src/boost/libs/utility/OptionalPointee.html new file mode 100644 index 000000000..c3c7e44eb --- /dev/null +++ b/src/boost/libs/utility/OptionalPointee.html @@ -0,0 +1,159 @@ +<HTML> +<Head> +<Title>OptionalPointee Concept</Title> +</HEAD> +<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" + ALINK="#ff0000"> +<IMG SRC="../../boost.png" + ALT="C++ Boost" width="277" height="86"> +<!--end header--> +<BR Clear> +<H1>Concept: OptionalPointee</H1> + +<h3>Description</h3> +A type is a model of <i>OptionalPointee</i> if it points to (or refers to) a value +that may not exist. That is, if it has a <b>pointee</b> which might be <b>valid</b> +(existent) or <b>invalid</b> (inexistent); and it is possible to test whether the +pointee is valid or not. +This model does <u>not</u> imply pointer semantics: i.e., it does not imply shallow copy nor +aliasing. +<h3>Notation</h3> +<Table> + <TR> + <TD VAlign=top> <tt>T</tt> </TD> + <TD VAlign=top> is a type that is a model of OptionalPointee</TD> + </TR> + <TR> + <TD VAlign=top> <tt>t</tt> </TD> + <TD VAlign=top> is an object of type <tt>T</tt> or possibly <tt>const T</tt></TD> + </tr> +</table> +<h3>Definitions</h3> +<h3>Valid expressions</h3> +<Table border> + <TR> + <TH> Name </TH> + <TH> Expression </TH> + <TH> Return type </TH> + <TH> Semantics </TH> + </TR> + <TR> + <TD VAlign=top>Value Access</TD> + <TD VAlign=top> <tt>*t</tt></TD> + <TD VAlign=top> <tt>T&</tt></TD> + <TD VAlign=top>If the pointee is valid returns a reference to + the pointee.<br> + If the pointee is invalid the result is <i>undefined</i>.</TD> + <TD VAlign=top> </TD> + </TR> + <TR> + <TD VAlign=top>Value Access</TD> + <TD VAlign=top> <tt>t-><i>xyz</i></tt></TD> + <TD VAlign=top> <tt>T*</tt></TD> + <TD VAlign=top>If the pointee is valid returns a builtin pointer to the pointee.<br> + If the pointee is invalid the result is <i>undefined</i> (It might not even return NULL).<br> + </TD> + <TD VAlign=top> </TD> + </TR> + <TR> + <TD VAlign=top>Validity Test</TD> + <TD VAlign=top> <tt>bool(t)</tt></TD> + <TD VAlign=top> bool </TD> + <TD VAlign=top>If the pointee is valid returns true.<br> + If the pointee is invalid returns false.</TD> + <TD VAlign=top></TD> + </TR> + <TR> + <TD VAlign=top>Invalidity Test</TD> + <TD VAlign=top> <tt>!t</tt></TD> + <TD VAlign=top> bool </TD> + <TD VAlign=top>If the pointee is valid returns false.<br> + If the pointee is invalid returns true.</TD> + <TD VAlign=top></TD> + </TR> +</table> + + +<h3>Models</h3> + +<UL> + <LI><tt>pointers, both builtin and smart.</tt> + <LI><tt>boost::optional<></tt> +</UL> + +<HR> +<h3>OptionalPointee and relational operations</h3> +<p>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.<br> +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.<br> +But boost::optional<T>, on the other hand, which is also a model of OptionalPointee, has +deep-copy and deep-relational semantics.<br> +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.<br> +Still, the concept itsef can be used to define <i>deep</i> relational tests that can +be used in generic code with any type which models OptionalPointee:</p> +<a name="equal"></a> +<p><u>Equivalence relation:</u></p> +<pre>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) ; } +} ; +</pre> +<p>The preceding generic function and function object have the following semantics:<br> +If both <b>x</b> and <b>y</b> have valid pointees, it compares values via <code>(*x == *y)</code>.<br> +If only one has a valid pointee, returns <code>false</code>.<br> +If both have invalid pointees, returns <code>true</code>.</p> +<a name="less"></a> +<p><u>Less-than relation:</u></p> +<pre>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) ; } +} ; +</pre> +<p>The preceding generic function and function object have the following semantics:<br> +If <b>y</b> has an invalid pointee, returns <code>false</code>.<br> +Else, if <b>x</b> has an invalid pointee, returns <code>true</code>.<br> +Else, ( <b>x</b> and <b>y</b> have valid pointees), compares values via <code>(*x < +*y).</code></p> +<p><br> +All these functions and function +objects are is implemented in <a href="../../boost/utility/compare_pointees.hpp">compare_pointees.hpp</a></p> +<p>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.</p> + +<h3>Acknowledgements</h3> +<p>Based on the original concept developed by Augustus Saunders. + +<br> +</p> +<HR> +<TABLE> +<TR valign=top> +<TD nowrap>Copyright © 2003</TD><TD> +<A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A> +</TD></TR></TABLE> + +<p>Distributed under the Boost Software License, Version 1.0. See +<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p> + +</BODY> +</HTML> diff --git a/src/boost/libs/utility/README.md b/src/boost/libs/utility/README.md new file mode 100644 index 000000000..49d3c288d --- /dev/null +++ b/src/boost/libs/utility/README.md @@ -0,0 +1,24 @@ +# ![Boost.Utility](doc/logo.png) + +Boost.Utility, part of collection of the [Boost C++ Libraries](https://github.com/boostorg), provides a number of smaller components, too small to be called libraries in their own right. See the documentation for the list of components. + +### Directories + +* **doc** - Documentation sources +* **include** - Interface headers of Boost.Utility +* **test** - Boost.Utility unit tests + +### More information + +* [Documentation](https://boost.org/libs/utility) +* [Report bugs](https://github.com/boostorg/utility/issues/new). Be sure to mention Boost version, Boost.Utility component, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. +* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). + +### Build status + +Master: [![Travis CI](https://travis-ci.org/boostorg/utility.svg?branch=master)](https://travis-ci.org/boostorg/utility) +Develop: [![Travis CI](https://travis-ci.org/boostorg/utility.svg?branch=develop)](https://travis-ci.org/boostorg/utility) + +### License + +Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). diff --git a/src/boost/libs/utility/call_traits.htm b/src/boost/libs/utility/call_traits.htm new file mode 100644 index 000000000..b4fe3ee90 --- /dev/null +++ b/src/boost/libs/utility/call_traits.htm @@ -0,0 +1,755 @@ +<html> + +<head> +<meta http-equiv="Content-Type" +content="text/html; charset=iso-8859-1"> +<meta name="Template" +content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot"> +<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"> +<title>Call Traits</title> +</head> + +<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" +vlink="#800080"> + +<h1><img src="../../boost.png" width="276" height="86">Header +<<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1> + +<p>All of the contents of <boost/call_traits.hpp> are +defined inside namespace boost.</p> + +<p>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 "<a href="#refs">references to references</a>" +never occur, and that parameters are passed in the most efficient +manner possible (see <a href="#examples">examples</a>). 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. </p> + +<p>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).</p> + +<table border="0" cellpadding="7" cellspacing="1" width="797"> + <tr> + <td valign="top" width="17%" bgcolor="#008080"><p + align="center">Existing practice</p> + </td> + <td valign="top" width="35%" bgcolor="#008080"><p + align="center">call_traits equivalent</p> + </td> + <td valign="top" width="32%" bgcolor="#008080"><p + align="center">Description</p> + </td> + <td valign="top" width="16%" bgcolor="#008080"><p + align="center">Notes</p> + </td> + </tr> + <tr> + <td valign="top" width="17%"><p align="center">T<br> + (return by value)</p> + </td> + <td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p> + </td> + <td valign="top" width="32%">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.</td> + <td valign="top" width="16%"><p align="center">2</p> + </td> + </tr> + <tr> + <td valign="top" width="17%"><p align="center">T&<br> + (return value)</p> + </td> + <td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p> + </td> + <td valign="top" width="32%">Defines a type that + represents a reference to type T. Use for functions that + would normally return a T&.</td> + <td valign="top" width="16%"><p align="center">1</p> + </td> + </tr> + <tr> + <td valign="top" width="17%"><p align="center">const + T&<br> + (return value)</p> + </td> + <td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p> + </td> + <td valign="top" width="32%">Defines a type that + represents a constant reference to type T. Use for + functions that would normally return a const T&.</td> + <td valign="top" width="16%"><p align="center">1</p> + </td> + </tr> + <tr> + <td valign="top" width="17%"><p align="center">const + T&<br> + (function parameter)</p> + </td> + <td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p> + </td> + <td valign="top" width="32%">Defines a type that + represents the "best" way to pass a parameter + of type T to a function.</td> + <td valign="top" width="16%"><p align="center">1,3</p> + </td> + </tr> +</table> + +<p>Notes:</p> + +<ol> + <li>If T is already reference type, then call_traits is + defined such that <a href="#refs">references to + references</a> do not occur (requires partial + specialization).</li> + <li>If T is an array type, then call_traits defines <code>value_type</code> + 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!).</li> + <li>If T is a small built in type or a pointer, then <code>param_type</code> + is defined as <code>T const</code>, instead of <code>T + const&</code>. 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).</li> +</ol> + +<p> </p> + +<h3>Copy constructibility</h3> + +<p>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:</p> + +<table border="0" cellpadding="7" cellspacing="1" width="766"> + <tr> + <td valign="top" width="17%"> </td> + <td valign="top" colspan="5" width="85%" + bgcolor="#008080"><p align="center">To:</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#008080">From:</td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">T</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">value_type</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">reference</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">const_reference</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">param_type</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">T</td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">N</p> + </td> + <td valign="top" width="17%"><p align="center">N</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">N</p> + </td> + <td valign="top" width="17%"><p align="center">N</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">?</p> + </td> + <td valign="top" width="17%"><p align="center">N</p> + </td> + <td valign="top" width="17%"><p align="center">N</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + </tr> +</table> + +<p> </p> + +<p>If T is an assignable type the following assignments are +possible:</p> + +<table border="0" cellpadding="7" cellspacing="1" width="766"> + <tr> + <td valign="top" width="17%"> </td> + <td valign="top" colspan="5" width="85%" + bgcolor="#008080"><p align="center">To:</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#008080">From:</td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">T</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">value_type</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">reference</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">const_reference</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">param_type</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">T</td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">Y</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + <td valign="top" width="17%"><p align="center">-</p> + </td> + </tr> +</table> + +<p> </p> + +<h3><a name="examples"></a>Examples</h3> + +<p>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.</p> + +<table border="0" cellpadding="7" cellspacing="1" width="766"> + <tr> + <td valign="top" width="17%"> </td> + <td valign="top" colspan="5" width="85%" + bgcolor="#008080"><p align="center">Call_traits type:</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#008080"><p + align="center">Original type T</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">value_type</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">reference</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">const_reference</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">param_type</p> + </td> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">Applies to:</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">myclass</p> + </td> + <td valign="top" width="17%"><p align="center">myclass</p> + </td> + <td valign="top" width="17%"><p align="center">myclass&</p> + </td> + <td valign="top" width="17%"><p align="center">const + myclass&</p> + </td> + <td valign="top" width="17%"><p align="center">myclass + const&</p> + </td> + <td valign="top" width="17%"><p align="center">All user + defined types.</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">int</p> + </td> + <td valign="top" width="17%"><p align="center">int</p> + </td> + <td valign="top" width="17%"><p align="center">int&</p> + </td> + <td valign="top" width="17%"><p align="center">const + int&</p> + </td> + <td valign="top" width="17%"><p align="center">int const</p> + </td> + <td valign="top" width="17%"><p align="center">All small + built-in types.</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">int*</p> + </td> + <td valign="top" width="17%"><p align="center">int*</p> + </td> + <td valign="top" width="17%"><p align="center">int*&</p> + </td> + <td valign="top" width="17%"><p align="center">int*const&</p> + </td> + <td valign="top" width="17%"><p align="center">int* const</p> + </td> + <td valign="top" width="17%"><p align="center">All + pointer types.</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">int&</p> + </td> + <td valign="top" width="17%"><p align="center">int&</p> + </td> + <td valign="top" width="17%"><p align="center">int&</p> + </td> + <td valign="top" width="17%"><p align="center">const + int&</p> + </td> + <td valign="top" width="17%"><p align="center">int&</p> + </td> + <td valign="top" width="17%"><p align="center">All + reference types.</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">const int&</p> + </td> + <td valign="top" width="17%"><p align="center">const + int&</p> + </td> + <td valign="top" width="17%"><p align="center">const + int&</p> + </td> + <td valign="top" width="17%"><p align="center">const + int&</p> + </td> + <td valign="top" width="17%"><p align="center">const + int&</p> + </td> + <td valign="top" width="17%"><p align="center">All + constant-references.</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">int[3]</p> + </td> + <td valign="top" width="17%"><p align="center">const int*</p> + </td> + <td valign="top" width="17%"><p align="center">int(&)[3]</p> + </td> + <td valign="top" width="17%"><p align="center">const int(&)[3]</p> + </td> + <td valign="top" width="17%"><p align="center">const int* + const</p> + </td> + <td valign="top" width="17%"><p align="center">All array + types.</p> + </td> + </tr> + <tr> + <td valign="top" width="17%" bgcolor="#C0C0C0"><p + align="center">const int[3]</p> + </td> + <td valign="top" width="17%"><p align="center">const int*</p> + </td> + <td valign="top" width="17%"><p align="center">const int(&)[3]</p> + </td> + <td valign="top" width="17%"><p align="center">const int(&)[3]</p> + </td> + <td valign="top" width="17%"><p align="center">const int* + const</p> + </td> + <td valign="top" width="17%"><p align="center">All + constant-array types.</p> + </td> + </tr> +</table> + +<p> </p> + +<h4>Example 1:</h4> + +<p>The following class is a trivial class that stores some type T +by value (see the <a href="test/call_traits_test.cpp">call_traits_test.cpp</a> +file), the aim is to illustrate how each of the available +call_traits typedefs may be used:</p> + +<pre>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){} + +};</pre> + +<h4><a name="refs"></a>Example 2 (the reference to reference +problem):</h4> + +<p>Consider the definition of std::binder1st:</p> + +<pre>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; +}; </pre> + +<p>Now consider what happens in the relatively common case that +the functor takes its second argument as a reference, that +implies that <code>Operation::second_argument_type</code> is a +reference type, <code>operator()</code> 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 <code>operator()</code> +to use call_traits:</p> + +<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre> + +<p>Now in the case that <code>Operation::second_argument_type</code> +is a reference type, the argument is passed as a reference, and +the no "reference to reference" occurs.</p> + +<h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4> + +<p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>, +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):</p> + +<pre>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); +}</pre> + +<p>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.</p> + +<h4><a name="ex4"></a>Example 4 (optimising fill):</h4> + +<p>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 <a +href="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>), +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:</p> + +<pre>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); +}</pre> + +<p>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.</p> + +<p>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.</p> + +<h3>Rationale</h3> + +<p>The following notes are intended to briefly describe the +rational behind choices made in call_traits.</p> + +<p>All user-defined types follow "existing practice" +and need no comment.</p> + +<p>Small built-in types (what the standard calls fundamental +types [3.9.1]) differ from existing practice only in the <i>param_type</i> +typedef. In this case passing "T const" is compatible +with existing practice, but may improve performance in some cases +(see <a href="#ex4">Example 4</a>), in any case this should never +be any worse than existing practice.</p> + +<p>Pointers follow the same rational as small built-in types.</p> + +<p>For reference types the rational follows <a href="#refs">Example +2</a> - 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).</p> + +<p>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:</p> + +<pre>template <class T> +struct A +{ + void foo(T t); +};</pre> + +<p><font face="Times New Roman">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:</font></p> + +<pre>template <class T> +void A<T>::foo(T t) +{ + T dup(t); // doesn't compile for case that T is an array. +}</pre> + +<p>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:</p> + +<pre>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. +}</pre> + +<p>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 - <a +href="#ex3">Example 3</a> 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).</p> + +<hr> + +<p>Revised 01 September 2000</p> + + <p> + Copyright 2000 Steve Cleary, Beman Dawes, Howard + Hinnant and John Maddock. <br/> + Use, modification and distribution are subject to the + Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt + or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> + http://www.boost.org/LICENSE_1_0.txt + </a>). + </p> +</body> +</html> + diff --git a/src/boost/libs/utility/checked_delete.html b/src/boost/libs/utility/checked_delete.html new file mode 100644 index 000000000..1b9325615 --- /dev/null +++ b/src/boost/libs/utility/checked_delete.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv=refresh content="0; URL=../core/doc/html/core/checked_delete.html"> +<title>Automatic redirection</title> +</head> +<body> +Automatic redirection failed, please go to +<a href="../core/doc/html/core/checked_delete.html">checked_delete.html</a>. <hr> +<p>© Copyright Beman Dawes, 2001</p> +<p>Distributed under the Boost Software License, Version 1.0. (See accompanying +file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy +at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p> +</body> +</html> diff --git a/src/boost/libs/utility/compressed_pair.htm b/src/boost/libs/utility/compressed_pair.htm new file mode 100644 index 000000000..0b99bf7ac --- /dev/null +++ b/src/boost/libs/utility/compressed_pair.htm @@ -0,0 +1,16 @@ + +<!-- +Copyright 2014 Daniel James. +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) +--> + +<html> +<head> + <meta http-equiv="refresh" content="0; URL=doc/html/compressed_pair.html"> +</head> +<body> +Automatic redirection failed, please go to +<a href="doc/html/compressed_pair.html">doc/html/compressed_pair.html</a> +</body> +</html> diff --git a/src/boost/libs/utility/enable_if.html b/src/boost/libs/utility/enable_if.html new file mode 100644 index 000000000..0cd1a985a --- /dev/null +++ b/src/boost/libs/utility/enable_if.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv=refresh content="0; URL=../core/doc/html/core/enable_if.html"> +<title>Automatic redirection</title> +</head> +<body> +Automatic redirection failed, please go to +<a href="../core/doc/html/core/enable_if.html">enable_if.html</a>. <hr> +<p>© Copyright Beman Dawes, 2001</p> +<p>Distributed under the Boost Software License, Version 1.0. (See accompanying +file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy +at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p> +</body> +</html> diff --git a/src/boost/libs/utility/identity_type/index.html b/src/boost/libs/utility/identity_type/index.html new file mode 100644 index 000000000..00b33623c --- /dev/null +++ b/src/boost/libs/utility/identity_type/index.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + <head> + <meta http-equiv="refresh" content="0; URL=doc/html/index.html"> + </head> + <body> + Automatic redirection failed, click this + <a href="doc/html/index.html">link</a> <hr> + <p>© Copyright Lorenzo Caminiti, 2009-2012</p> + <p>Distributed under the Boost Software License, Version 1.0 (see + accompanying file <a href="../../../LICENSE_1_0.txt"> + LICENSE_1_0.txt</a> or a copy at + <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p> + </body> +</html> diff --git a/src/boost/libs/utility/identity_type/test/Jamfile.v2 b/src/boost/libs/utility/identity_type/test/Jamfile.v2 new file mode 100644 index 000000000..5cb50366d --- /dev/null +++ b/src/boost/libs/utility/identity_type/test/Jamfile.v2 @@ -0,0 +1,16 @@ + +# Copyright (C) 2009-2012 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 +# (see accompanying file LICENSE_1_0.txt or a copy at +# http://www.boost.org/LICENSE_1_0.txt) +# Home at http://www.boost.org/libs/utility/identity_type + +import testing ; + +compile-fail var_error.cpp ; +run var.cpp ; +run template.cpp ; +run abstract.cpp ; +run noncopyable.cpp ; +run paren.cpp ; + diff --git a/src/boost/libs/utility/identity_type/test/abstract.cpp b/src/boost/libs/utility/identity_type/test/abstract.cpp new file mode 100644 index 000000000..39b10c35a --- /dev/null +++ b/src/boost/libs/utility/identity_type/test/abstract.cpp @@ -0,0 +1,35 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include <boost/utility/identity_type.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/add_reference.hpp> +#include <boost/type_traits/remove_reference.hpp> + +//[abstract +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +template<typename T, bool b> +struct abstract { + static const bool value = b; + virtual void f(T const& x) = 0; // Pure virtual function. +}; + +TMP_ASSERT( + boost::remove_reference< // Add and remove + BOOST_IDENTITY_TYPE(( // reference for + boost::add_reference< // abstract type. + abstract<int, true> + >::type + )) + >::type +); +//] + +int main() { return 0; } + diff --git a/src/boost/libs/utility/identity_type/test/noncopyable.cpp b/src/boost/libs/utility/identity_type/test/noncopyable.cpp new file mode 100644 index 000000000..2819e6850 --- /dev/null +++ b/src/boost/libs/utility/identity_type/test/noncopyable.cpp @@ -0,0 +1,25 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include <boost/utility/identity_type.hpp> +#include <boost/static_assert.hpp> +#include <boost/noncopyable.hpp> + +//[noncopyable +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +template<typename T, T init> +struct noncopyable : boost::noncopyable { + static const T value = init; +}; + +TMP_ASSERT(BOOST_IDENTITY_TYPE((noncopyable<bool, true>))); +//] + +int main() { return 0; } + diff --git a/src/boost/libs/utility/identity_type/test/paren.cpp b/src/boost/libs/utility/identity_type/test/paren.cpp new file mode 100644 index 000000000..51b355fe9 --- /dev/null +++ b/src/boost/libs/utility/identity_type/test/paren.cpp @@ -0,0 +1,35 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include <boost/utility/identity_type.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_const.hpp> +#include <map> + +//[paren +#define TMP_ASSERT_PAREN(parenthesized_metafunction) \ + /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \ + BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value) + +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +// Specify only extra parenthesis `((...))`. +TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>)); + +// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro. +TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>))); +//] + +//[paren_always +TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`. + +TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro. +//] + +int main() { return 0; } + diff --git a/src/boost/libs/utility/identity_type/test/template.cpp b/src/boost/libs/utility/identity_type/test/template.cpp new file mode 100644 index 000000000..dfc109795 --- /dev/null +++ b/src/boost/libs/utility/identity_type/test/template.cpp @@ -0,0 +1,48 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include <boost/utility/identity_type.hpp> +#include <map> +#include <iostream> + +//[template_f_decl +#define ARG(type, n) type arg ## n + +template<typename T> +void f( // Prefix macro with `typename` in templates. + ARG(typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1) +) { + std::cout << arg1[0] << std::endl; +} +//] + +//[template_g_decl +template<typename T> +void g( + std::map<int, T> arg1 +) { + std::cout << arg1[0] << std::endl; +} +//] + +int main() { + //[template_f_call + std::map<int, char> a; + a[0] = 'a'; + + f<char>(a); // OK... + // f(a); // ... but error. + //] + + //[template_g_call + g<char>(a); // OK... + g(a); // ... and also OK. + //] + + return 0; +} + diff --git a/src/boost/libs/utility/identity_type/test/var.cpp b/src/boost/libs/utility/identity_type/test/var.cpp new file mode 100644 index 000000000..9ed165d71 --- /dev/null +++ b/src/boost/libs/utility/identity_type/test/var.cpp @@ -0,0 +1,26 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include <map> + +#define VAR(type, n) type var ## n + +VAR(int, 1); // OK. + +//[var_typedef +typedef std::map<int, char> map_type; +VAR(map_type, 3); // OK. +//] + +//[var_ok +#include <boost/utility/identity_type.hpp> + +VAR(BOOST_IDENTITY_TYPE((std::map<int, char>)), 4); // OK. +//] + +int main() { return 0; } + diff --git a/src/boost/libs/utility/identity_type/test/var_error.cpp b/src/boost/libs/utility/identity_type/test/var_error.cpp new file mode 100644 index 000000000..efb9743f5 --- /dev/null +++ b/src/boost/libs/utility/identity_type/test/var_error.cpp @@ -0,0 +1,18 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include <map> + +//[var_error +#define VAR(type, n) type var ## n + +VAR(int, 1); // OK. +VAR(std::map<int, char>, 2); // Error. +//] + +int main() { return 0; } + diff --git a/src/boost/libs/utility/in_place_factories.html b/src/boost/libs/utility/in_place_factories.html new file mode 100644 index 000000000..8eb7ea8d4 --- /dev/null +++ b/src/boost/libs/utility/in_place_factories.html @@ -0,0 +1,296 @@ +<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd"> + +<HTML> + +<HEAD> +<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"> +<TITLE>In_place_factory Documentation</TITLE> +</HEAD> + +<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080"> +<H2 align="left"><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86"></H2> + +<blockquote> + <blockquote> + <blockquote> + <blockquote> + <blockquote> + <blockquote> +<H2 align="left">Header <<A +HREF="../../boost/utility/in_place_factory.hpp">boost/utility/in_place_factory.hpp</A>> </H2> + +<H2 align="left">Header <<A +HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_place_factory.hpp</A>> </H2> + + </blockquote> + </blockquote> + </blockquote> + </blockquote> + </blockquote> +</blockquote> +<p> </p> + +<H2>Contents</H2> +<DL CLASS="page-index"> + <DT><A HREF="#mot">Motivation</A></DT> + <DT><A HREF="#framework">Framework</A></DT> + <DT><A HREF="#specification">Specification</A></DT> + <DT><A HREF="#container-usage">Container-side Usage</A></DT> + <DT><A HREF="#user-usage">User-side Usage</A></DT> +</DL> + +<HR> + +<H2><A NAME="mot"></A>Motivation</H2> + +<p>Suppose we have a class</p> +<pre>struct X +{ + X ( int, std::string ) ; +} ;</pre> +<p>And a container for it which supports an empty state (that is, which can contain zero objects):</p> +<pre>struct C +{ + C() : contained_(0) {} + ~C() { delete contained_ ; } + X* contained_ ; +} ;</pre> +<p>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:</p> +<pre>struct C +{ + C() : contained_(0) {} + C ( X const& v ) : contained_ ( new X(v) ) {} + ~C() { delete contained_ ; } + X* contained_ ; +} ;</pre> +<p>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</p> +<pre>void foo() +{ + // Temporary object created. + C c( X(123,"hello") ) ; +} +</pre> +<p>A solution to this problem is to support direct construction of the contained +object right in the container's storage.<br> +In this scheme, the user supplies the arguments for the X constructor +directly to the container:</p> +<pre>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_ ; +} ;</pre> +<pre>void foo() +{ + // Wrapped object constructed in-place + // No temporary created. + C c(123,"hello") ; +} +</pre> +<p>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).</p> + +<H2><A NAME="framework"></A>Framework</H2> +<p> +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.<br> +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) +</p> +<p>For this purpose, the framework provides two families of classes collectively called: InPlaceFactories and TypedInPlaceFactories.<br> +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..</p> +<p>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.<br> +The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:</p> +<pre>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") ) ; +} +</pre> + +<HR> + +<H2><A NAME="specification">Specification</A></H2> + +<p>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.</p> +<PRE>namespace boost { + +struct in_place_factory_base {} ; + +template<class A0> +class in_place_factory : public in_place_factory_base +{ + public:</PRE> + +<PRE> in_place_factory ( A0 const& a0 ) : m_a0(a0) {} + + template< class T > + void apply ( void* address ) const + { + new (address) T(m_a0); + } + + private:</PRE> + +<PRE> A0 const& m_a0 ; +} ; + +template<class A0> +in_place_factory<A0> in_place ( A0 const& a0 ) +{ + return in_place_factory<A0>(a0); +} +</PRE> + +<p>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.</p> +<PRE>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:</PRE> + +<PRE> typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {} + + void apply ( void* address ) const + { + new (address) T(m_a0); + } + + private:</PRE> + +<PRE> 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); +}</PRE> + +<PRE>} +</PRE> + +<p>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.<br> +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.<br> +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.</p> + +<HR> + +<h2><A NAME="container-usage">Container-side Usage</a></h2> + +<p>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.<br> +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.<br> +The correct function overload must be based on the only distinctive and common +characteristic of all the classes in each family, the base class.<br> +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): +</p> +<pre>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_ ; +} ; +</pre> + +<hr> + +<h2><A NAME="user-usage">User-side Usage</a></h2> + +<p>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.<br> +The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.<br> +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'.</p> +<pre>void foo() +{ + C a( in_place(123,"hello") ) ; // in_place_factory passed + C b( in_place<X>(456,"world") ) ; // typed_in_place_factory passed +} +</pre> + +<P>Revised September 17, 2004</P> +<p>© Copyright Fernando Luis Cacciola Carballal, 2004</p> +<p> Use, modification, and distribution are subject to the Boost Software +License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt"> +LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +www.boost.org/LICENSE_1_0.txt</a>)</p> +<P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>, +the latest version of this file can be found at <A +HREF="http://www.boost.org">www.boost.org</A>, and the boost +<A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P> +</BODY> +</HTML> diff --git a/src/boost/libs/utility/index.html b/src/boost/libs/utility/index.html new file mode 100644 index 000000000..c2af44f9e --- /dev/null +++ b/src/boost/libs/utility/index.html @@ -0,0 +1,50 @@ +<html> + <head> + <meta http-equiv="Content-Language" content="en-us"> + <meta name="GENERATOR" content="Microsoft FrontPage 5.0"> + <meta name="ProgId" content="FrontPage.Editor.Document"> + <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> + <title>Boost Utility Library</title> + </head> + <body bgcolor="#FFFFFF"> + <h1><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86" align="center">Boost + Utility Library</h1> + <p>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.</p> + <p>But that doesn't mean there isn't useful stuff here. Take a look:</p> + <ul> + <li><a href="doc/html/base_from_member.html">base_from_member</a></li> + <li><a href="utility.htm#BOOST_BINARY">BOOST_BINARY</a></li> + <li><a href="call_traits.htm">call_traits</a></li> + <li><a href="doc/html/compressed_pair.html">compressed_pair</a></li> + <li><a href="in_place_factories.html">in_place_factory</a></li> + <li><a href="iterator_adaptors.htm">iterator_adaptors</a></li> + <li><a href="operators.htm">operators</a></li> + <li><a href="utility.htm#result_of">result_of</a></li> + <li><a href="throw_exception.html">throw_exception</a></li> + <li><a href="utility.htm">utility</a></li> + <li><a href="doc/html/string_ref.html">string_ref</a></li> + <li><a href="value_init.htm">value_init</a></li> + </ul> + <p>Over time useful stuff here has moved to more appropriate Boost libraries:</p> + <ul> + <li><a href="../core/doc/html/core/addressof.html">addressof</a> (moved to Boost.Core)</li> + <li><a href="../core/doc/html/core/checked_delete.html">checked_delete</a> (moved to Boost.Core)</li> + <li><a href="../type_traits/doc/html/boost_typetraits/reference/declval.html">declval</a> (moved to Boost.TypeTraits)</li> + <li><a href="../core/doc/html/core/enable_if.html">enable_if</a> (moved to Boost.Core)</li> + <li><a href="../iterator/doc/generator_iterator.htm">generator iterator adaptors</a> (moved to Boost.Iterator)</li> + <li><a href="../iterator/doc/html/iterator/algorithms/next_prior.html">next/prior</a> (moved to Boost.Iterator)</li> + <li><a href="../core/doc/html/core/noncopyable.html">noncopyable</a> (moved to Boost.Core)</li> + <li><a href="../io/doc/html/io.html">ostream_string</a> (moved to Boost.IO)</li> + </ul> + <hr> + <p>© Copyright Beman Dawes, 2001</p> + <p>Distributed under the Boost Software License, Version 1.0. (See + accompanying file <a href="../../LICENSE_1_0.txt"> + LICENSE_1_0.txt</a> or copy at + <a href="http://www.boost.org/LICENSE_1_0.txt"> + www.boost.org/LICENSE_1_0.txt</a>)</p> + <p>Revised + <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->07 November, 2006<!--webbot bot="Timestamp" endspan i-checksum="39368" --></p> + </body> +</html> diff --git a/src/boost/libs/utility/iterator_adaptors.htm b/src/boost/libs/utility/iterator_adaptors.htm new file mode 100644 index 000000000..7232ac297 --- /dev/null +++ b/src/boost/libs/utility/iterator_adaptors.htm @@ -0,0 +1,11 @@ +<!-- Copyright David Abrahams 2004. 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) --> +<html> +<head> +<meta http-equiv="refresh" content="0; URL=../iterator/doc/index.html"> +</head> +<body> +This documentation moved to <a href="../iterator/doc/index.html">../iterator/doc/index.html</a>. +</body> +</html> diff --git a/src/boost/libs/utility/meta/libraries.json b/src/boost/libs/utility/meta/libraries.json new file mode 100644 index 000000000..ca7c4b6e9 --- /dev/null +++ b/src/boost/libs/utility/meta/libraries.json @@ -0,0 +1,126 @@ +[ + { + "key": "utility", + "name": "Utility", + "authors": [ + "Dave Abrahams and others" + ], + "description": "Class noncopyable plus checked_delete(), checked_array_delete(), next(), prior() function templates, plus base-from-member idiom.", + "documentation": "utility.htm", + "category": [ + "Algorithms", + "Function-objects", + "Memory", + "Miscellaneous", + "Patterns" + ] + }, + { + "key": "utility/call_traits", + "name": "Call Traits", + "authors": [ + "John Maddock, Howard Hinnant, et al" + ], + "description": "Defines types for passing parameters.", + "documentation": "call_traits.htm", + "category": [ + "Generic" + ] + }, + { + "key": "utility/compressed_pair", + "name": "Compressed Pair", + "authors": [ + "John Maddock, Howard Hinnant, et al" + ], + "description": "Empty member optimization.", + "documentation": "compressed_pair.htm", + "category": [ + "Data", + "Patterns" + ] + }, + { + "key": "utility/identity_type", + "name": "Identity Type", + "authors": [ + "Lorenzo Caminiti" + ], + "description": "Wrap types within round parenthesis so they can always be passed as macro parameters.", + "documentation": "identity_type/", + "category": [ + "Preprocessor" + ], + "maintainers": [ + "Lorenzo Caminiti <lorcaminiti -at- gmail.com>" + ] + }, + { + "key": "utility/in_place_factories", + "name": "In Place Factory, Typed In Place Factory", + "authors": [ + "Fernando Cacciola" + ], + "description": "Generic in-place construction of contained objects with a variadic argument-list.", + "documentation": "in_place_factories.html", + "category": [ + "Generic" + ] + }, + { + "key": "utility/operators", + "name": "Operators", + "authors": [ + "Dave Abrahams", + "Jeremy Siek" + ], + "description": "Templates ease arithmetic classes and iterators.", + "documentation": "operators.htm", + "category": [ + "Generic", + "Iterators", + "Math" + ], + "maintainers": [ + "Daniel Frey <d.frey -at- gmx.de>" + ] + }, + { + "key": "utility/result_of", + "name": "Result Of", + "description": "Determines the type of a function call expression.", + "documentation": "utility.htm#result_of", + "category": [ + "Function-objects" + ], + "authors": "", + "maintainers": [ + "Daniel Walker <daniel.j.walker -at- gmail.com>" + ] + }, + { + "key": "utility/string_ref", + "name": "string_ref", + "description": "String view templates.", + "documentation": "doc/html/string_ref.html", + "category": [ + "Containers" + ], + "authors": "Marshall Clow", + "maintainers": [ + "Marshall Clow <marshall -at- idio.com>" + ] + }, + { + "key": "utility/value_initialized", + "name": "Value Initialized", + "authors": [ + "Fernando Cacciola" + ], + "description": "Wrapper for uniform-syntax value initialization, based on the original idea of David Abrahams.", + "documentation": "value_init.htm", + "category": [ + "Miscellaneous" + ] + } +] diff --git a/src/boost/libs/utility/operators.htm b/src/boost/libs/utility/operators.htm new file mode 100644 index 000000000..d2c6682cb --- /dev/null +++ b/src/boost/libs/utility/operators.htm @@ -0,0 +1,2144 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> + +<html> + <head> + <meta name="generator" content= + "HTML Tidy for Windows (vers 1st August 2002), see www.w3.org"> + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + + <title>Header <boost/operators.hpp> Documentation</title> + </head> + + <body text="black" bgcolor="white" link="blue" vlink="purple" alink="red"> + <h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align= + "middle" width="277" height="86">Header <cite><<a href= + "../../boost/operators.hpp">boost/operators.hpp</a>></cite></h1> + + <p>The header <cite><<a href= + "../../boost/operators.hpp">boost/operators.hpp</a>></cite> supplies + several sets of class templates (in namespace <code>boost</code>). These + templates define operators at namespace scope in terms of a minimal + number of fundamental operators provided by the class.</p> + + <h2><a name="contents">Contents</a></h2> + + <ul> + <li><a href="#contents">Contents</a></li> + + <li> + <a href="#rationale">Rationale</a> + + <ul> + <li><a href="#semantics">Summary of Template Semantics</a></li> + + <li><a href="#concepts_note">Use of <i>concepts</i></a></li> + </ul> + </li> + + <li> + <a href="#usage">Usage</a> + + <ul> + <li> + <a href="#two_arg">Two-Argument Template Forms</a> + + <ul> + <li><a href="#two_arg_gen">General Considerations</a></li> + + <li><a href="#mixed_arithmetics">Mixed arithmetics</a></li> + </ul> + </li> + + <li><a href="#chaining">Base Class Chaining and Object + Size</a></li> + + <li><a href="#explicit_instantiation">Separate, Explicit + Instantiation</a></li> + + <li><a href="#portability">Requirement Portability</a></li> + </ul> + </li> + + <li><a href="#example">Example</a></li> + + <li> + <a href="#arithmetic">Arithmetic operators</a> + + <ul> + <li> + <a href="#smpl_oprs">Simple Arithmetic Operators</a> + + <ul> + <li><a href="#ordering">Ordering Note</a></li> + + <li><a href="#symmetry">Symmetry Note</a></li> + </ul> + </li> + + <li><a href="#grpd_oprs">Grouped Arithmetic Operators</a></li> + + <li><a href="#ex_oprs">Example Templates</a></li> + + <li><a href="#a_demo">Arithmetic Operators Demonstration and Test + Program</a></li> + </ul> + </li> + + <li> + <a href="#deref">Dereference Operators and Iterator Helpers</a> + + <ul> + <li><a href="#dereference">Dereference operators</a></li> + + <li><a href="#grpd_iter_oprs">Grouped Iterator Operators</a></li> + + <li> + <a href="#iterator">Iterator Helpers</a> + + <ul> + <li><a href="#iterator_helpers_notes">Iterator Helper + Notes</a></li> + </ul> + </li> + + <li><a href="#i_demo">Iterator Demonstration and Test + Program</a></li> + </ul> + </li> + + <li><a href="#contributors">Contributors</a></li> + + <li><a href="#old_lib_note">Note for Users of Older Versions</a></li> + </ul> + + <h2><a name="rationale">Rationale</a></h2> + + <p>Overloaded operators for class types typically occur in groups. If you + can write <code>x + y</code>, you probably also want to be able + to write <code>x += y</code>. If you can write <code>x < y,</code> you + also want <code>x > y, x >= y,</code> and <code>x <= y</code>. + Moreover, unless your class has really surprising behavior, some of these + related operators can be defined in terms of others (e.g. <code>x >= y + is equivalent to !(x < y)</code>). Replicating this boilerplate for + multiple classes is both tedious and error-prone. The <cite><a href= + "../../boost/operators.hpp">boost/operators.hpp</a></cite> templates help + by generating operators for you at namespace scope based on other + operators you've defined in your class.</p> + + <p>If, for example, you declare a class like this:</p> + + <blockquote> +<pre> +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--(); +}; +</pre> + </blockquote> + + <p>then the <code><a href="#operators1">operators<></a></code> + template adds more than a dozen additional operators, such as + <code>operator></code>, <code><=</code>, <code>>=</code>, and + (binary) <code>+</code>. <a href="#two_arg">Two-argument forms</a> of the + templates are also provided to allow interaction with other types.</p> + + <h3>Summary of Template <a name="semantics">Semantics</a></h3> + + <ol> + <li>Each operator template completes the concept(s) it describes by + defining overloaded operators for its target class.</li> + + <li>The name of an operator class template indicates the <a href= + "#concepts_note">concept</a> that its target class will model.</li> + + <li>Usually, the target class uses an instantation of the operator + class template as a base class. Some operator templates support an <a + href="#explicit_instantiation">alternate method</a>.</li> + + <li>The concept can be compound, <i>i.e.</i> it may represent a common + combination of other, simpler concepts.</li> + + <li>Most operator templates require their target class to support + operations related to the operators supplied by the template. In + accordance with widely accepted <a href= + "http://www.gotw.ca/gotw/004.htm">coding style recommendations</a>, the + target class is often required to supply the assignment counterpart + operator of the concept's "main operator." For example, the + <code>addable</code> template requires <code>operator+=(T + const&)</code> and in turn supplies <code>operator+(T const&, T + const&)</code>.</li> + </ol> + + <h3>Use of <i><a name="concepts_note">concepts</a></i></h3> + + <p>The discussed concepts are not necessarily the standard library's + concepts (CopyConstructible, <i>etc.</i>), although some of them could + be; they are what we call <i>concepts with a small 'c'</i>. In + particular, they are different from the former ones in that they <em>do + not</em> 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 (<i>e.g.</i> effects of + evaluating of <code>a += b</code> and + <code>a = a + b</code> 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 + (<i>e.g.</i> <code>operator<</code> should return a type convertible + to <code>bool</code>, and <code>T::operator-=</code> should return type + convertible to <code>T</code>). Such "loose" requirements make operators + library applicable to broader set of target classes from different + domains, <i>i.e.</i> eventually more useful.</p> + + <h2><a name="usage">Usage</a></h2> + + <h3><a name="two_arg">Two-Argument</a> Template Forms</h3> + + <h4><a name="two_arg_gen">General Considerations</a></h4> + + <p>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 <a href="#example">example</a>, 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 <code>T + U</code> is of type <code>T</code>, then + <code>T</code> (not <code>U</code>) should be derived from <code><a href= + "#addable2">addable<T, U></a></code>. The comparison templates + (<code><a href="#less_than_comparable2">less_than_comparable<T, + U></a></code>, <code><a href= + "#equality_comparable2">equality_comparable<T, U></a></code>, + <code><a href="#equivalent2">equivalent<T, U></a></code>, and + <code><a href="#partially_ordered2">partially_ordered<T, + U></a></code>) are exceptions to this guideline, since the return type + of the operators they define is <code>bool</code>.</p> + + <p>On compilers which do not support partial specialization, the + two-argument forms must be specified by using the names shown below with + the trailing <code>'2'</code>. The single-argument forms with the + trailing <code>'1'</code> are provided for symmetry and to enable certain + applications of the <a href="#chaining">base class chaining</a> + technique.</p> + + <h4><a name="mixed_arithmetics">Mixed Arithmetics</a></h4> + + <p>Another application of the two-argument template forms is for mixed + arithmetics between a type <code>T</code> and a type <code>U</code> that + is convertible to <code>T</code>. 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.</p> + + <p>With respect to the operator overloading assume <i>e.g.</i> that + <code>U</code> is <code>int</code>, that <code>T</code> is an + user-defined unlimited integer type, and that <code>double + operator-(double, const T&)</code> exists. If one wants to compute + <code>int - T</code> and does not provide <code>T operator-(int, const + T&)</code>, the compiler will consider <code>double operator-(double, + const T&)</code> to be a better match than <code>T operator-(const + T&, const T&)</code>, 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 + (<code><a href="#subtractable2_left">subtractable2_left<T, + U></a></code>, <code><a href="#dividable2_left">dividable2_left<T, + U></a></code>, <code><a href="#modable2_left">modable2_left<T, + U></a></code>) that define the signatures for non-commutative + operators where <code>U</code> appears on the left hand side + (<code>operator-(const U&, const T&)</code>, + <code>operator/(const U&, const T&)</code>, <code>operator%(const + U&, const T&)</code>).</p> + + <p>With respect to the performance observe that when one uses the single + type binary operator for mixed type arithmetics, the type <code>U</code> + argument has to be converted to type <code>T</code>. In practice, + however, there are often more efficient implementations of, say + <code>T::operator-=(const U&)</code> that avoid unnecessary + conversions from <code>U</code> to <code>T</code>. 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 <code>U</code> to <code>T</code> 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.</p> + + <h3>Base Class <a name="chaining">Chaining</a> and Object Size</h3> + + <p>Every operator class template, except the <a href= + "#ex_oprs">arithmetic examples</a> and the <a href="#iterator">iterator + helpers</a>, has an additional, but optional, template type parameter + <code>B</code>. 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 <a + href="#old_lib_note">note for users of older versions</a> for more + details). To provide support for a group of operators, use the + <code>B</code> parameter to chain operator templates into a single-base + class hierarchy, demostrated in the <a href="#example">usage example</a>. + 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.</p> + + <p><strong>Caveat:</strong> to chain to a base class which is + <em>not</em> a Boost operator template when using the <a href= + "#two_arg">single-argument form</a> of a Boost operator template, you + must specify the operator template with the trailing <code>'1'</code> 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.</p> + + <h3>Separate, <a name="explicit_instantiation">Explicit + Instantiation</a></h3> + + <p>On some compilers (<i>e.g.</i> 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:</p> + + <blockquote> +<pre> + 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>; +</pre> + </blockquote> + + <p>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:</p> + + <ul> + <li><code><a href= + "#dereferenceable">dereferenceable<></a></code></li> + + <li><code><a href="#indexable">indexable<></a></code></li> + + <li>Any composite operator template that includes at least one of the + above</li> + </ul> + + <p>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. + <code>less_than_comparable<myclass></code> can not be found + by ADL according to the rules given by 3.4.2/2, since myclass is + not an associated class of + <code>less_than_comparable<myclass></code>. + Thus only use this technique if all else fails.</p> + + <h3>Requirement <a name="portability">Portability</a></h3> + + <p>Many compilers (<i>e.g.</i> 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 <code><a href= + "#operators1">operators<></a></code> and <code><a href= + "#operators2">operators2<></a></code> 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.</p> + + <h2><a name="example">Example</a></h2> + + <p>This example shows how some of the <a href="#arithmetic">arithmetic + operator templates</a> can be used with a geometric point class + (template).</p> +<pre> +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); +</pre> + + <h2><a name="arithmetic">Arithmetic</a> Operators</h2> + + <p>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, <i>etc</i>. 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.</p> + + <p>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.</p> + + <h3><a name="smpl_oprs">Simple Arithmetic Operators</a></h3> + + <p>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 <code>B</code>, which is not shown, for the + <a href="#chaining">base class chaining</a> technique.</p> + + <p>The primary operand type <code>T</code> needs to be of class type, + built-in types are not supported.</p> + + <table cellpadding="5" border="1" align="center"> + <caption> + Simple Arithmetic Operator Template Classes + </caption> + + <tr> + <td colspan="3"> + <table align="center" border="1"> + <caption> + <em>Key</em> + </caption> + + <tr> + <td><code>T</code>: primary operand type</td> + + <td><code>U</code>: alternate operand type</td> + </tr> + + <tr> + <td><code>t</code>, <code>t1</code>: values of type + <code>T</code></td> + + <td><code>u</code>: value of type <code>U</code></td> + </tr> + </table> + </td> + </tr> + + <tr> + <th>Template</th> + + <th>Supplied Operations</th> + + <th>Requirements</th> + </tr> + + <tr> + <td><code><a name= + "less_than_comparable1">less_than_comparable<T></a></code><br> + <code>less_than_comparable1<T></code></td> + + <td><code>bool operator>(const T&, const T&)</code><br> + <code>bool operator<=(const T&, const T&)</code><br> + <code>bool operator>=(const T&, const T&)</code></td> + + <td><code>t < t1</code>.<br> + Return convertible to <code>bool</code>. See the <a href= + "#ordering">Ordering Note</a>.</td> + </tr> + + <tr> + <td><code><a name="less_than_comparable2">less_than_comparable<T, + U></a></code><br> + <code>less_than_comparable2<T, U></code></td> + + <td><code>bool operator<=(const T&, const U&)</code><br> + <code>bool operator>=(const T&, const U&)</code><br> + <code>bool operator>(const U&, const T&)</code><br> + <code>bool operator<(const U&, const T&)</code><br> + <code>bool operator<=(const U&, const T&)</code><br> + <code>bool operator>=(const U&, const T&)</code></td> + + <td><code>t < u</code>. <code>t > u</code>.<br> + Returns convertible to <code>bool</code>. See the <a href= + "#ordering">Ordering Note</a>.</td> + </tr> + + <tr> + <td><code><a name= + "equality_comparable1">equality_comparable<T></a></code><br> + <code>equality_comparable1<T></code></td> + + <td><code>bool operator!=(const T&, const T&)</code></td> + + <td><code>t == t1</code>.<br> + Return convertible to <code>bool</code>.</td> + </tr> + + <tr> + <td><code><a name="equality_comparable2">equality_comparable<T, + U></a></code><br> + <code>equality_comparable2<T, U></code></td> + + <td><code>bool operator==(const U&, const T&)</code><br> + <code>bool operator!=(const U&, const T&)</code><br> + <code>bool operator!=(const T&, const U&)</code></td> + + <td><code>t == u</code>.<br> + Return convertible to <code>bool</code>.</td> + </tr> + + <tr> + <td><code><a name="addable1">addable<T></a></code><br> + <code>addable1<T></code></td> + + <td><code>T operator+(const T&, const T&)</code></td> + + <td><code>T temp(t); temp += t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="addable2">addable<T, U></a></code><br> + <code>addable2<T, U></code></td> + + <td><code>T operator+(const T&, const U&)</code><br> + <code>T operator+(const U&, const T& )</code></td> + + <td><code>T temp(t); temp += u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name= + "subtractable1">subtractable<T></a></code><br> + <code>subtractable1<T></code></td> + + <td><code>T operator-(const T&, const T&)</code></td> + + <td><code>T temp(t); temp -= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="subtractable2">subtractable<T, + U></a></code><br> + <code>subtractable2<T, U></code></td> + + <td><code>T operator-(const T&, const U&)</code></td> + + <td><code>T temp(t); temp -= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="subtractable2_left">subtractable2_left<T, + U></a></code></td> + + <td><code>T operator-(const U&, const T&)</code></td> + + <td><code>T temp(u); temp -= t</code>.<br> + Return convertible to <code>T</code>.</td> + </tr> + + <tr> + <td><code><a name= + "multipliable1">multipliable<T></a></code><br> + <code>multipliable1<T></code></td> + + <td><code>T operator*(const T&, const T&)</code></td> + + <td><code>T temp(t); temp *= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="multipliable2">multipliable<T, + U></a></code><br> + <code>multipliable2<T, U></code></td> + + <td><code>T operator*(const T&, const U&)</code><br> + <code>T operator*(const U&, const T&)</code></td> + + <td><code>T temp(t); temp *= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="dividable1">dividable<T></a></code><br> + <code>dividable1<T></code></td> + + <td><code>T operator/(const T&, const T&)</code></td> + + <td><code>T temp(t); temp /= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="dividable2">dividable<T, U></a></code><br> + <code>dividable2<T, U></code></td> + + <td><code>T operator/(const T&, const U&)</code></td> + + <td><code>T temp(t); temp /= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="dividable2_left">dividable2_left<T, + U></a></code></td> + + <td><code>T operator/(const U&, const T&)</code></td> + + <td><code>T temp(u); temp /= t</code>.<br> + Return convertible to <code>T</code>.</td> + </tr> + + <tr> + <td><code><a name="modable1">modable<T></a></code><br> + <code>modable1<T></code></td> + + <td><code>T operator%(const T&, const T&)</code></td> + + <td><code>T temp(t); temp %= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="modable2">modable<T, U></a></code><br> + <code>modable2<T, U></code></td> + + <td><code>T operator%(const T&, const U&)</code></td> + + <td><code>T temp(t); temp %= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="modable2_left">modable2_left<T, + U></a></code></td> + + <td><code>T operator%(const U&, const T&)</code></td> + + <td><code>T temp(u); temp %= t</code>.<br> + Return convertible to <code>T</code>.</td> + </tr> + + <tr> + <td><code><a name="orable1">orable<T></a></code><br> + <code>orable1<T></code></td> + + <td><code>T operator|(const T&, const T&)</code></td> + + <td><code>T temp(t); temp |= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="orable2">orable<T, U></a></code><br> + <code>orable2<T, U></code></td> + + <td><code>T operator|(const T&, const U&)</code><br> + <code>T operator|(const U&, const T&)</code></td> + + <td><code>T temp(t); temp |= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="andable1">andable<T></a></code><br> + <code>andable1<T></code></td> + + <td><code>T operator&(const T&, const T&)</code></td> + + <td><code>T temp(t); temp &= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="andable2">andable<T, U></a></code><br> + <code>andable2<T, U></code></td> + + <td><code>T operator&(const T&, const U&)</code><br> + <code>T operator&(const U&, const T&)</code></td> + + <td><code>T temp(t); temp &= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="xorable1">xorable<T></a></code><br> + <code>xorable1<T></code></td> + + <td><code>T operator^(const T&, const T&)</code></td> + + <td><code>T temp(t); temp ^= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="xorable2">xorable<T, U></a></code><br> + <code>xorable2<T, U></code></td> + + <td><code>T operator^(const T&, const U&)</code><br> + <code>T operator^(const U&, const T&)</code></td> + + <td><code>T temp(t); temp ^= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name= + "incrementable">incrementable<T></a></code></td> + + <td><code>T operator++(T&, int)</code></td> + + <td><code>T temp(t); ++t</code><br> + Return convertible to <code>T</code>.</td> + </tr> + + <tr> + <td><code><a name= + "decrementable">decrementable<T></a></code></td> + + <td><code>T operator--(T&, int)</code></td> + + <td><code>T temp(t); --t;</code><br> + Return convertible to <code>T</code>.</td> + </tr> + + <tr> + <td><code><a name= + "left_shiftable1">left_shiftable<T></a></code><br> + <code>left_shiftable1<T></code></td> + + <td><code>T operator<<(const T&, const T&)</code></td> + + <td><code>T temp(t); temp <<= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="left_shiftable2">left_shiftable<T, + U></a></code><br> + <code>left_shiftable2<T, U></code></td> + + <td><code>T operator<<(const T&, const U&)</code></td> + + <td><code>T temp(t); temp <<= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name= + "right_shiftable1">right_shiftable<T></a></code><br> + <code>right_shiftable1<T></code></td> + + <td><code>T operator>>(const T&, const T&)</code></td> + + <td><code>T temp(t); temp >>= t1</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="right_shiftable2">right_shiftable<T, + U></a></code><br> + <code>right_shiftable2<T, U></code></td> + + <td><code>T operator>>(const T&, const U&)</code></td> + + <td><code>T temp(t); temp >>= u</code>.<br> + Return convertible to <code>T</code>. See the <a href= + "#symmetry">Symmetry Note</a>.</td> + </tr> + + <tr> + <td><code><a name="equivalent1">equivalent<T></a></code><br> + <code>equivalent1<T></code></td> + + <td><code>bool operator==(const T&, const T&)</code></td> + + <td><code>t < t1</code>.<br> + Return convertible to <code>bool</code>. See the <a href= + "#ordering">Ordering Note</a>.</td> + </tr> + + <tr> + <td><code><a name="equivalent2">equivalent<T, U></a></code><br> + <code>equivalent2<T, U></code></td> + + <td><code>bool operator==(const T&, const U&)</code></td> + + <td><code>t < u</code>. <code>t > u</code>.<br> + Returns convertible to <code>bool</code>. See the <a href= + "#ordering">Ordering Note</a>.</td> + </tr> + + <tr> + <td><code><a name= + "partially_ordered1">partially_ordered<T></a></code><br> + <code>partially_ordered1<T></code></td> + + <td><code>bool operator>(const T&, const T&)</code><br> + <code>bool operator<=(const T&, const T&)</code><br> + <code>bool operator>=(const T&, const T&)</code></td> + + <td><code>t < t1</code>. <code>t == t1</code>.<br> + Returns convertible to <code>bool</code>. See the <a href= + "#ordering">Ordering Note</a>.</td> + </tr> + + <tr> + <td><code><a name="partially_ordered2">partially_ordered<T, + U></a></code><br> + <code>partially_ordered2<T, U></code></td> + + <td><code>bool operator<=(const T&, const U&)</code><br> + <code>bool operator>=(const T&, const U&)</code><br> + <code>bool operator>(const U&, const T&)</code><br> + <code>bool operator<(const U&, const T&)</code><br> + <code>bool operator<=(const U&, const T&)</code><br> + <code>bool operator>=(const U&, const T&)</code></td> + + <td><code>t < u</code>. <code>t > u</code>. <code>t == + u</code>.<br> + Returns convertible to <code>bool</code>. See the <a href= + "#ordering">Ordering Note</a>.</td> + </tr> + </table> + + <h4><a name="ordering">Ordering</a> Note</h4> + + <p>The <code><a href= + "#less_than_comparable1">less_than_comparable<T></a></code> and + <code><a href="#partially_ordered1">partially_ordered<T></a></code> + templates provide the same set of operations. However, the workings of + <code><a href= + "#less_than_comparable1">less_than_comparable<T></a></code> assume + that all values of type <code>T</code> can be placed in a total order. If + that is not true (<i>e.g.</i> Not-a-Number values in IEEE floating point + arithmetic), then <code><a href= + "#partially_ordered1">partially_ordered<T></a></code> should be + used. The <code><a href= + "#partially_ordered1">partially_ordered<T></a></code> template can + be used for a totally-ordered type, but it is not as efficient as + <code><a href= + "#less_than_comparable1">less_than_comparable<T></a></code>. This + rule also applies for <code><a href= + "#less_than_comparable2">less_than_comparable<T, U></a></code> and + <code><a href="#partially_ordered2">partially_ordered<T, + U></a></code> with respect to the ordering of all <code>T</code> and + <code>U</code> values, and for both versions of <code><a href= + "#equivalent1">equivalent<></a></code>. The solution for <code><a + href="#equivalent1">equivalent<></a></code> is to write a custom + <code>operator==</code> for the target class.</p> + + <h4><a name="symmetry">Symmetry</a> Note</h4> + + <p>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 <code>operator+</code> for a class + <code>T</code> as an example:</p> +<pre> +T operator+( const T& lhs, const T& rhs ) +{ + return T( lhs ) += rhs; +} +</pre> + This would be a normal implementation of <code>operator+</code>, but it + is not an efficient one. An unnamed local copy of <code>lhs</code> is + created, <code>operator+=</code> is called on it and it is copied to the + function return value (which is another unnamed object of type + <code>T</code>). The standard doesn't generally allow the intermediate + object to be optimized away: + + <blockquote> + 3.7.2/2: Automatic storage duration<br> + <br> + 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. + </blockquote> + The reference to 12.8 is important for us: + + <blockquote> + 12.8/15: Copying class objects<br> + ...<br> + 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. + </blockquote> + This optimization is known as the named return value optimization (NRVO), + which leads us to the following implementation for + <code>operator+</code>: +<pre> +T operator+( const T& lhs, const T& rhs ) +{ + T nrv( lhs ); + nrv += rhs; + return nrv; +} +</pre> + 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: +<pre> +T operator+( T lhs, const T& rhs ) +{ + return lhs += rhs; +} +</pre> + The difference to the first implementation is that <code>lhs</code> is + not taken as a constant reference used to create a copy; instead, + <code>lhs</code> is a by-value parameter, thus it is already the copy + needed. This allows another optimization (12.2/2) for some cases. + Consider <code>a + b + c</code> where the result of + <code>a + b</code> is not copied when used as <code>lhs</code> + when adding <code>c</code>. 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 <code>operator+</code> now has a different function signature. Also, + the number of objects created differs for + <code>(a + b ) + c</code> and + <code>a + ( b + c )</code>. 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 + <code>BOOST_FORCE_SYMMETRIC_OPERATORS</code> in your user-config. This + will force the NRVO-friendly implementation to be used even for compilers + that don't implement the NRVO. <br> + <br> + + <h3><a name="grpd_oprs">Grouped Arithmetic Operators</a></h3> + + <p>The following templates provide common groups of related operations. + For example, since a type which is addable is usually also subractable, + the <code><a href="#additive1">additive</a></code> template provides the + combined operators of both. The grouped operator templates have an + additional optional template parameter <code>B</code>, which is not + shown, for the <a href="#chaining">base class chaining</a> technique.</p> + + <table cellpadding="5" border="1" align="center"> + <caption> + Grouped Arithmetic Operator Template Classes + </caption> + + <tr> + <td colspan="2"> + <table align="center" border="1"> + <caption> + <em>Key</em> + </caption> + + <tr> + <td><code>T</code>: primary operand type</td> + + <td><code>U</code>: alternate operand type</td> + </tr> + </table> + </td> + </tr> + + <tr> + <th>Template</th> + + <th>Component Operator Templates</th> + </tr> + + <tr> + <td><code><a name= + "totally_ordered1">totally_ordered<T></a></code><br> + <code>totally_ordered1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#less_than_comparable1">less_than_comparable<T></a></code></li> + + <li><code><a href= + "#equality_comparable1">equality_comparable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="totally_ordered2">totally_ordered<T, + U></a></code><br> + <code>totally_ordered2<T, U></code></td> + + <td> + <ul> + <li><code><a href= + "#less_than_comparable2">less_than_comparable<T, + U></a></code></li> + + <li><code><a href= + "#equality_comparable2">equality_comparable<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="additive1">additive<T></a></code><br> + <code>additive1<T></code></td> + + <td> + <ul> + <li><code><a href="#addable1">addable<T></a></code></li> + + <li><code><a href= + "#subtractable1">subtractable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="additive2">additive<T, U></a></code><br> + <code>additive2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#addable2">addable<T, U></a></code></li> + + <li><code><a href="#subtractable2">subtractable<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "multiplicative1">multiplicative<T></a></code><br> + <code>multiplicative1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#multipliable1">multipliable<T></a></code></li> + + <li><code><a href= + "#dividable1">dividable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="multiplicative2">multiplicative<T, + U></a></code><br> + <code>multiplicative2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#multipliable2">multipliable<T, + U></a></code></li> + + <li><code><a href="#dividable2">dividable<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "integer_multiplicative1">integer_multiplicative<T></a></code><br> + + <code>integer_multiplicative1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#multiplicative1">multiplicative<T></a></code></li> + + <li><code><a href="#modable1">modable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "integer_multiplicative2">integer_multiplicative<T, + U></a></code><br> + <code>integer_multiplicative2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#multiplicative2">multiplicative<T, + U></a></code></li> + + <li><code><a href="#modable2">modable<T, U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="arithmetic1">arithmetic<T></a></code><br> + <code>arithmetic1<T></code></td> + + <td> + <ul> + <li><code><a href="#additive1">additive<T></a></code></li> + + <li><code><a href= + "#multiplicative1">multiplicative<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="arithmetic2">arithmetic<T, U></a></code><br> + <code>arithmetic2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#additive2">additive<T, + U></a></code></li> + + <li><code><a href="#multiplicative2">multiplicative<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "integer_arithmetic1">integer_arithmetic<T></a></code><br> + <code>integer_arithmetic1<T></code></td> + + <td> + <ul> + <li><code><a href="#additive1">additive<T></a></code></li> + + <li><code><a href= + "#integer_multiplicative1">integer_multiplicative<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="integer_arithmetic2">integer_arithmetic<T, + U></a></code><br> + <code>integer_arithmetic2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#additive2">additive<T, + U></a></code></li> + + <li><code><a href= + "#integer_multiplicative2">integer_multiplicative<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="bitwise1">bitwise<T></a></code><br> + <code>bitwise1<T></code></td> + + <td> + <ul> + <li><code><a href="#xorable1">xorable<T></a></code></li> + + <li><code><a href="#andable1">andable<T></a></code></li> + + <li><code><a href="#orable1">orable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="bitwise2">bitwise<T, U></a></code><br> + <code>bitwise2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#xorable2">xorable<T, U></a></code></li> + + <li><code><a href="#andable2">andable<T, U></a></code></li> + + <li><code><a href="#orable2">orable<T, U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "unit_steppable">unit_steppable<T></a></code></td> + + <td> + <ul> + <li><code><a href= + "#incrementable">incrementable<T></a></code></li> + + <li><code><a href= + "#decrementable">decrementable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="shiftable1">shiftable<T></a></code><br> + <code>shiftable1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#left_shiftable1">left_shiftable<T></a></code></li> + + <li><code><a href= + "#right_shiftable1">right_shiftable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="shiftable2">shiftable<T, U></a></code><br> + <code>shiftable2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#left_shiftable2">left_shiftable<T, + U></a></code></li> + + <li><code><a href="#right_shiftable2">right_shiftable<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "ring_operators1">ring_operators<T></a></code><br> + <code>ring_operators1<T></code></td> + + <td> + <ul> + <li><code><a href="#additive1">additive<T></a></code></li> + + <li><code><a href= + "#multipliable1">multipliable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="ring_operators2">ring_operators<T, + U></a></code><br> + <code>ring_operators2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#additive2">additive<T, + U></a></code></li> + + <li><code><a href="#subtractable2_left">subtractable2_left<T, + U></a></code></li> + + <li><code><a href="#multipliable2">multipliable<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "ordered_ring_operators1">ordered_ring_operators<T></a></code><br> + + <code>ordered_ring_operators1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#ring_operators1">ring_operators<T></a></code></li> + + <li><code><a href= + "#totally_ordered1">totally_ordered<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "ordered_ring_operators2">ordered_ring_operators<T, + U></a></code><br> + <code>ordered_ring_operators2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#ring_operators2">ring_operators<T, + U></a></code></li> + + <li><code><a href="#totally_ordered2">totally_ordered<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "field_operators1">field_operators<T></a></code><br> + <code>field_operators1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#ring_operators1">ring_operators<T></a></code></li> + + <li><code><a href= + "#dividable1">dividable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="field_operators2">field_operators<T, + U></a></code><br> + <code>field_operators2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#ring_operators2">ring_operators<T, + U></a></code></li> + + <li><code><a href="#dividable2">dividable<T, + U></a></code></li> + + <li><code><a href="#dividable2_left">dividable2_left<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "ordered_field_operators1">ordered_field_operators<T></a></code><br> + + <code>ordered_field_operators1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#field_operators1">field_operators<T></a></code></li> + + <li><code><a href= + "#totally_ordered1">totally_ordered<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "ordered_field_operators2">ordered_field_operators<T, + U></a></code><br> + <code>ordered_field_operators2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#field_operators2">field_operators<T, + U></a></code></li> + + <li><code><a href="#totally_ordered2">totally_ordered<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "euclidean_ring_operators1">euclidean_ring_operators<T></a></code><br> + + <code>euclidean_ring_operators1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#ring_operators1">ring_operators<T></a></code></li> + + <li><code><a href= + "#dividable1">dividable<T></a></code></li> + + <li><code><a href="#modable1">modable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "euclidean_ring_operators2">euclidean_ring_operators<T, + U></a></code><br> + <code>euclidean_ring_operators2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#ring_operators2">ring_operators<T, + U></a></code></li> + + <li><code><a href="#dividable2">dividable<T, + U></a></code></li> + + <li><code><a href="#dividable2_left">dividable2_left<T, + U></a></code></li> + + <li><code><a href="#modable2">modable<T, U></a></code></li> + + <li><code><a href="#modable2_left">modable2_left<T, + U></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "ordered_euclidean_ring_operators1">ordered_euclidean_ring_operators<T></a></code><br> + + <code>ordered_euclidean_ring_operators1<T></code></td> + + <td> + <ul> + <li><code><a href= + "#euclidean_ring_operators1">euclidean_ring_operators<T></a></code></li> + + <li><code><a href= + "#totally_ordered1">totally_ordered<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "ordered_euclidean_ring_operators2">ordered_euclidean_ring_operators<T, + U></a></code><br> + <code>ordered_euclidean_ring_operators2<T, U></code></td> + + <td> + <ul> + <li><code><a href= + "#euclidean_ring_operators2">euclidean_ring_operators<T, + U></a></code></li> + + <li><code><a href="#totally_ordered2">totally_ordered<T, + U></a></code></li> + </ul> + </td> + </tr> + </table> + + <h4>Spelling: euclidean vs. euclidian</h4> + + <p>Older versions of the Boost.Operators library used + "<code>euclidian</code>", but it was pointed out that + "<code>euclidean</code>" is the more common spelling. + To be compatible with older version, the library now supports + both spellings. + </p> + + <h3><a name="ex_oprs">Example</a> Templates</h3> + + <p>The arithmetic operator class templates <code><a href= + "#operators1">operators<></a></code> and <code><a href= + "#operators2">operators2<></a></code> are examples of + non-extensible operator grouping classes. These legacy class templates, + from previous versions of the header, cannot be used for <a href= + "#chaining">base class chaining</a>.</p> + + <table cellpadding="5" border="1" align="center"> + <caption> + Final Arithmetic Operator Template Classes + </caption> + + <tr> + <td colspan="2"> + <table align="center" border="1"> + <caption> + <em>Key</em> + </caption> + + <tr> + <td><code>T</code>: primary operand type</td> + + <td><code>U</code>: alternate operand type</td> + </tr> + </table> + </td> + </tr> + + <tr> + <th>Template</th> + + <th>Component Operator Templates</th> + </tr> + + <tr> + <td><code><a name="operators1">operators<T></a></code></td> + + <td> + <ul> + <li><code><a href= + "#totally_ordered1">totally_ordered<T></a></code></li> + + <li><code><a href= + "#integer_arithmetic1">integer_arithmetic<T></a></code></li> + + <li><code><a href="#bitwise1">bitwise<T></a></code></li> + + <li><code><a href= + "#unit_steppable">unit_steppable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="operators2">operators<T, U></a></code><br> + <code>operators2<T, U></code></td> + + <td> + <ul> + <li><code><a href="#totally_ordered2">totally_ordered<T, + U></a></code></li> + + <li><code><a href="#integer_arithmetic2">integer_arithmetic<T, + U></a></code></li> + + <li><code><a href="#bitwise2">bitwise<T, U></a></code></li> + </ul> + </td> + </tr> + </table> + + <h3><a name="a_demo">Arithmetic Operators Demonstration</a> and Test + Program</h3> + + <p>The <cite><a href="test/operators_test.cpp">operators_test.cpp</a></cite> + 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.</p> + + <h2><a name="deref">Dereference</a> Operators and Iterator Helpers</h2> + + <p>The <a href="#iterator">iterator helper</a> 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.</p> + + <p>The <a href="#dereference">dereference operators</a> were motivated by + the <a href="#iterator">iterator helpers</a>, 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 <code>operator-></code> and the + subscript <code>operator[]</code>)!</p> + + <p>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.</p> + + <h3><a name="dereference">Dereference</a> Operators</h3> + + <p>All the dereference operator templates in this table accept an + optional template parameter (not shown) to be used for <a href= + "#chaining">base class chaining</a>.</p> + + <table cellpadding="5" border="1" align="center"> + <caption> + Dereference Operator Template Classes + </caption> + + <tr> + <td colspan="3"> + <table align="center" border="1"> + <caption> + <em>Key</em> + </caption> + + <tr> + <td><code>T</code>: operand type</td> + + <td><code>P</code>: <code>pointer</code> type</td> + </tr> + + <tr> + <td><code>D</code>: <code>difference_type</code></td> + + <td><code>R</code>: <code>reference</code> type</td> + </tr> + + <tr> + <td><code>i</code>: object of type <code>T</code> (an + iterator)</td> + + <td><code>n</code>: object of type <code>D</code> (an + index)</td> + </tr> + </table> + </td> + </tr> + + <tr> + <th>Template</th> + + <th>Supplied Operations</th> + + <th>Requirements</th> + </tr> + + <tr> + <td><code><a name="dereferenceable">dereferenceable<T, + P></a></code></td> + + <td><code>P operator->() const</code></td> + + <td><code>*i</code>. Address of the returned value convertible + to <code>P</code>.</td> + </tr> + + <tr> + <td><code><a name="indexable">indexable<T, D, + R></a></code></td> + + <td><code>R operator[](D n) const</code></td> + + <td><code>*(i + n)</code>. Return of type + <code>R</code>.</td> + </tr> + </table> + + <h3><a name="grpd_iter_oprs">Grouped Iterator Operators</a></h3> + + <p>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 <code>B</code>, which is + not shown, to support <a href="#chaining">base class chaining</a>.</p> + + <table cellpadding="5" border="1" align="center"> + <caption> + Iterator Operator Class Templates + </caption> + + <tr> + <td colspan="2"> + <table align="center" border="1"> + <caption> + <em>Key</em> + </caption> + + <tr> + <td><code>T</code>: operand type</td> + + <td><code>P</code>: <code>pointer</code> type</td> + </tr> + + <tr> + <td><code>D</code>: <code>difference_type</code></td> + + <td><code>R</code>: <code>reference</code> type</td> + </tr> + + <tr> + <td><code>V</code>: <code>value_type</code></td> + + <td> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <th>Template</th> + + <th>Component Operator Templates</th> + </tr> + + <tr> + <td><code><a name="input_iteratable">input_iteratable<T, + P></a></code></td> + + <td> + <ul> + <li><code><a href= + "#equality_comparable1">equality_comparable<T></a></code></li> + + <li><code><a href= + "#incrementable">incrementable<T></a></code></li> + + <li><code><a href="#dereferenceable">dereferenceable<T, + P></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "output_iteratable">output_iteratable<T></a></code></td> + + <td> + <ul> + <li><code><a href= + "#incrementable">incrementable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name="forward_iteratable">forward_iteratable<T, + P></a></code></td> + + <td> + <ul> + <li><code><a href="#input_iteratable">input_iteratable<T, + P></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "bidirectional_iteratable">bidirectional_iteratable<T, + P></a></code></td> + + <td> + <ul> + <li><code><a href="#forward_iteratable">forward_iteratable<T, + P></a></code></li> + + <li><code><a href= + "#decrementable">decrementable<T></a></code></li> + </ul> + </td> + </tr> + + <tr> + <td><code><a name= + "random_access_iteratable">random_access_iteratable<T, P, D, + R></a></code></td> + + <td> + <ul> + <li><code><a href= + "#bidirectional_iteratable">bidirectional_iteratable<T, + P></a></code></li> + + <li><code><a href= + "#totally_ordered1">totally_ordered<T></a></code></li> + + <li><code><a href="#additive2">additive<T, + D></a></code></li> + + <li><code><a href="#indexable">indexable<T, D, + R></a></code></li> + </ul> + </td> + </tr> + </table> + + <h3><a name="iterator">Iterator</a> Helpers</h3> + + <p>There are also five iterator helper class templates, each + corresponding to a different iterator category. These classes cannot be + used for <a href="#chaining">base class chaining</a>. The following + summaries show that these class templates supply both the iterator + operators from the <a href="#grpd_iter_oprs">iterator operator class + templates</a> and the iterator typedef's required by the C++ standard + (<code>iterator_category</code>, <code>value_type</code>, + <i>etc.</i>).</p> + + <table cellpadding="5" border="1" align="center"> + <caption> + Iterator Helper Class Templates + </caption> + + <tr> + <td colspan="2"> + <table align="center" border="1"> + <caption> + <em>Key</em> + </caption> + + <tr> + <td><code>T</code>: operand type</td> + + <td><code>P</code>: <code>pointer</code> type</td> + </tr> + + <tr> + <td><code>D</code>: <code>difference_type</code></td> + + <td><code>R</code>: <code>reference</code> type</td> + </tr> + + <tr> + <td><code>V</code>: <code>value_type</code></td> + + <td><code>x1, x2</code>: objects of type <code>T</code></td> + </tr> + </table> + </td> + </tr> + + <tr> + <th>Template</th> + + <th>Operations & Requirements</th> + </tr> + + <tr valign="baseline"> + <td><code><a name="input_iterator_helper">input_iterator_helper<T, + V, D, P, R></a></code></td> + + <td> + Supports the operations and has the requirements of + + <ul> + <li><code><a href="#input_iteratable">input_iteratable<T, + P></a></code></li> + </ul> + </td> + </tr> + + <tr valign="baseline"> + <td><code><a name= + "output_iterator_helper">output_iterator_helper<T></a></code></td> + + <td> + Supports the operations and has the requirements of + + <ul> + <li><code><a href= + "#output_iteratable">output_iteratable<T></a></code></li> + </ul> + See also [<a href="#1">1</a>], [<a href="#2">2</a>]. + </td> + </tr> + + <tr valign="baseline"> + <td><code><a name= + "forward_iterator_helper">forward_iterator_helper<T, V, D, P, + R></a></code></td> + + <td> + Supports the operations and has the requirements of + + <ul> + <li><code><a href="#forward_iteratable">forward_iteratable<T, + P></a></code></li> + </ul> + </td> + </tr> + + <tr valign="baseline"> + <td><code><a name= + "bidirectional_iterator_helper">bidirectional_iterator_helper<T, + V, D, P, R></a></code></td> + + <td> + Supports the operations and has the requirements of + + <ul> + <li><code><a href= + "#bidirectional_iteratable">bidirectional_iteratable<T, + P></a></code></li> + </ul> + </td> + </tr> + + <tr valign="baseline"> + <td><code><a name= + "random_access_iterator_helper">random_access_iterator_helper<T, + V, D, P, R></a></code></td> + + <td> + Supports the operations and has the requirements of + + <ul> + <li><code><a href= + "#random_access_iteratable">random_access_iteratable<T, P, D, + R></a></code></li> + </ul> + To satisfy <cite><a href= + "http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a></cite>, + <code>x1 - x2</code> with return convertible to <code>D</code> is + also required. + </td> + </tr> + </table> + + <h4><a name="iterator_helpers_notes">Iterator Helper Notes</a></h4> + + <p><a name="1">[1]</a> Unlike other iterator helpers templates, + <code>output_iterator_helper</code> takes only one template parameter - + the type of its target class. Although to some it might seem like an + unnecessary restriction, the standard requires + <code>difference_type</code> and <code>value_type</code> of any output + iterator to be <code>void</code> (24.3.1 [lib.iterator.traits]), and + <code>output_iterator_helper</code> template respects this requirement. + Also, output iterators in the standard have void <code>pointer</code> and + <code>reference</code> types, so the <code>output_iterator_helper</code> + does the same.</p> + + <p><a name="2">[2]</a> 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), + <code>output_iterator_helper</code> supports the idiom by defining + <code>operator*</code> and <code>operator++</code> 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 <code><a href= + "../iterator/doc/function_output_iterator.html">boost::function_output_iterator</a></code> + adaptor:</p> +<pre> +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; +}; +</pre> + + <p>Note that support for self-proxying does not prevent you from using + <code>output_iterator_helper</code> to ease any other, different kind of + output iterator's implementation. If + <code>output_iterator_helper</code>'s target type provides its own + definition of <code>operator*</code> or/and <code>operator++</code>, then + these operators will get used and the ones supplied by + <code>output_iterator_helper</code> will never be instantiated.</p> + + <h3><a name="i_demo">Iterator Demonstration</a> and Test Program</h3> + + <p>The <cite><a href="test/iterators_test.cpp">iterators_test.cpp</a></cite> + 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.</p> + + <blockquote> +<pre> +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); +}; +</pre> + </blockquote> + + <p>Check the <a href="http://www.boost.org/development/testing.html">compiler status + report</a> for the test results with selected platforms.</p> + <hr> + + <h2><a name="contributors">Contributors</a></h2> + + <dl> + <dt><a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a></dt> + + <dd>Started the library and contributed the arithmetic operators in + <cite><a href= + "../../boost/operators.hpp">boost/operators.hpp</a></cite>.</dd> + + <dt><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a></dt> + + <dd>Contributed the <a href="#deref">dereference operators and iterator + helpers</a> in <cite><a href= + "../../boost/operators.hpp">boost/operators.hpp</a></cite>. Also + contributed <cite><a href= + "iterators_test.cpp">iterators_test.cpp</a></cite>.</dd> + + <dt><a href="http://www.boost.org/people/aleksey_gurtovoy.htm">Aleksey + Gurtovoy</a></dt> + + <dd>Contributed the code to support <a href="#chaining">base class + chaining</a> while remaining backward-compatible with old versions of + the library.</dd> + + <dt><a href="http://www.boost.org/people/beman_dawes.html">Beman Dawes</a></dt> + + <dd>Contributed <cite><a href= + "test/operators_test.cpp">operators_test.cpp</a></cite>.</dd> + + <dt><a href="http://www.boost.org/people/daryle_walker.html">Daryle Walker</a></dt> + + <dd>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.</dd> + + <dt>Helmut Zeisel</dt> + + <dd>Contributed the 'left' operators and added some grouped operator + classes.</dd> + + <dt>Daniel Frey</dt> + + <dd>Contributed the NRVO-friendly and symmetric implementation of + arithmetic operators.</dd> + + </dl> + + <h2>Note for Users of <a name="old_lib_note">Older Versions</a></h2> + + <p>The <a href="#chaining">changes in the library interface and + recommended usage</a> 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 <em>forced</em> change any existing code), + but the old usage is deprecated. Though it was arguably simpler and more + intuitive than using <a href="#chaining">base class chaining</a>, 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 + <code>point<int></code> from the <a href="#example">example</a> + above was 12-24 bytes on various compilers for the Win32 platform, + instead of the expected 8 bytes.</p> + + <p>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 <em>require</em> 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.</p> + + <p>Given the importance of the issue for the users of the library (which + aims to be useful for writing light-weight classes like + <code>MyInt</code> or <code>point<></code>), 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.</p> + <hr> + + <p>Revised: 7 Aug 2008</p> + + <p>Copyright © Beman Dawes, David Abrahams, 1999-2001.</p> + <p>Copyright © Daniel Frey, 2002-2009.</p> + <p>Use, modification, and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file + <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at + <a href="http://www.boost.org/LICENSE_1_0.txt"> + www.boost.org/LICENSE_1_0.txt</a>)</p> + </body> +</html> + diff --git a/src/boost/libs/utility/sublibs b/src/boost/libs/utility/sublibs new file mode 100644 index 000000000..721d7c4a9 --- /dev/null +++ b/src/boost/libs/utility/sublibs @@ -0,0 +1 @@ +The existance of this file tells the regression reporting programs that the directory contains sub-directories which are libraries.
\ No newline at end of file diff --git a/src/boost/libs/utility/test/Jamfile.v2 b/src/boost/libs/utility/test/Jamfile.v2 new file mode 100644 index 000000000..739edc0de --- /dev/null +++ b/src/boost/libs/utility/test/Jamfile.v2 @@ -0,0 +1,44 @@ +# Copyright David Abrahams 2003. + +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +# For more information, see http://www.boost.org/ + +# bring in rules for testing +import testing ; + +run base_from_member_test.cpp ; +run base_from_member_ref_test.cpp ; + +run binary_test.cpp ; + +run call_traits_test.cpp : -u ; + +run compressed_pair_test.cpp ; +run compressed_pair_final_test.cpp ; + +run iterators_test.cpp ; + +run operators_test.cpp ; + +compile result_of_test.cpp ; + +# compile-fail string_ref_from_rvalue.cpp ; +run string_ref_test1.cpp ; +run string_ref_test2.cpp ; +run string_ref_test_io.cpp ; +# compile-fail string_view_from_rvalue.cpp ; +compile string_view_constexpr_test1.cpp ; +run string_view_test1.cpp ; +run string_view_test2.cpp ; +run string_view_test_io.cpp ; + +run value_init_test.cpp ; +run value_init_workaround_test.cpp ; +run initialized_test.cpp ; +compile-fail value_init_test_fail1.cpp ; +compile-fail value_init_test_fail2.cpp ; +compile-fail value_init_test_fail3.cpp ; +compile-fail initialized_test_fail1.cpp ; +compile-fail initialized_test_fail2.cpp ; diff --git a/src/boost/libs/utility/test/base_from_member_ref_test.cpp b/src/boost/libs/utility/test/base_from_member_ref_test.cpp new file mode 100644 index 000000000..52f9b8704 --- /dev/null +++ b/src/boost/libs/utility/test/base_from_member_ref_test.cpp @@ -0,0 +1,29 @@ +// +// Test that a base_from_member<T&> can be properly constructed +// +// Copyright 2014 Agustin Berge +// +// 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 +// + +#include <boost/utility/base_from_member.hpp> + +#include <boost/core/lightweight_test.hpp> + +struct foo : boost::base_from_member<int&> +{ + explicit foo(int& ref) : boost::base_from_member<int&>(ref) + { + BOOST_TEST(&member == &ref); + } +}; + +int main() +{ + int i = 0; + foo f(i); + + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/base_from_member_test.cpp b/src/boost/libs/utility/test/base_from_member_test.cpp new file mode 100644 index 000000000..685c6387a --- /dev/null +++ b/src/boost/libs/utility/test/base_from_member_test.cpp @@ -0,0 +1,593 @@ +// Boost test program for base-from-member class templates -----------------// + +// Copyright 2001, 2003 Daryle Walker. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + +// See <http://www.boost.org/libs/utility/> for the library's home page. + +// Revision History +// 14 Jun 2003 Adjusted code for Boost.Test changes (Daryle Walker) +// 29 Aug 2001 Initial Version (Daryle Walker) + +#include <boost/core/lightweight_test.hpp> + +#include <boost/config.hpp> // for BOOST_NO_MEMBER_TEMPLATES +#include <boost/noncopyable.hpp> // for boost::noncopyable + +#include <boost/utility/base_from_member.hpp> // for boost::base_from_member + +#include <functional> // for std::less +#include <iostream> // for std::cout (std::ostream, std::endl indirectly) +#include <set> // for std::set +#include <typeinfo> // for std::type_info +#include <utility> // for std::pair, std::make_pair +#include <vector> // for std::vector + + +// Control if extra information is printed +#ifndef CONTROL_EXTRA_PRINTING +#define CONTROL_EXTRA_PRINTING 1 +#endif + + +// A (sub)object can be identified by its memory location and its type. +// Both are needed since an object can start at the same place as its +// first base class subobject and/or contained subobject. +typedef std::pair< void *, std::type_info const * > object_id; + +// Object IDs need to be printed +std::ostream & operator <<( std::ostream &os, object_id const &oi ); + +// A way to generate an object ID +template < typename T > + object_id identify( T &obj ); + +// A custom comparison type is needed +struct object_id_compare +{ + bool operator ()( object_id const &a, object_id const &b ) const; + +}; // object_id_compare + +// A singleton of this type coordinates the acknowledgements +// of objects being created and used. +class object_registrar + : private boost::noncopyable +{ +public: + + #ifndef BOOST_NO_MEMBER_TEMPLATES + template < typename T > + void register_object( T &obj ) + { this->register_object_imp( identify(obj) ); } + template < typename T, typename U > + void register_use( T &owner, U &owned ) + { this->register_use_imp( identify(owner), identify(owned) ); } + template < typename T, typename U > + void unregister_use( T &owner, U &owned ) + { this->unregister_use_imp( identify(owner), identify(owned) ); } + template < typename T > + void unregister_object( T &obj ) + { this->unregister_object_imp( identify(obj) ); } + #endif + + void register_object_imp( object_id obj ); + void register_use_imp( object_id owner, object_id owned ); + void unregister_use_imp( object_id owner, object_id owned ); + void unregister_object_imp( object_id obj ); + + typedef std::set<object_id, object_id_compare> set_type; + + typedef std::vector<object_id> error_record_type; + typedef std::vector< std::pair<object_id, object_id> > error_pair_type; + + set_type db_; + + error_pair_type defrauders_in_, defrauders_out_; + error_record_type overeager_, overkilled_; + +}; // object_registrar + +// A sample type to be used by containing types +class base_or_member +{ +public: + explicit base_or_member( int x = 1, double y = -0.25 ); + ~base_or_member(); + +}; // base_or_member + +// A sample type that uses base_or_member, used +// as a base for the main demonstration classes +class base_class +{ +public: + explicit base_class( base_or_member &x, base_or_member *y = 0, + base_or_member *z = 0 ); + + ~base_class(); + +private: + base_or_member *x_, *y_, *z_; + +}; // base_class + +// This bad class demonstrates the direct method of a base class needing +// to be initialized by a member. This is improper since the member +// isn't initialized until after the base class. +class bad_class + : public base_class +{ +public: + bad_class(); + ~bad_class(); + +private: + base_or_member x_; + +}; // bad_class + +// The first good class demonstrates the correct way to initialize a +// base class with a member. The member is changed to another base +// class, one that is initialized before the base that needs it. +class good_class_1 + : private boost::base_from_member<base_or_member> + , public base_class +{ + typedef boost::base_from_member<base_or_member> pbase_type; + typedef base_class base_type; + +public: + good_class_1(); + ~good_class_1(); + +}; // good_class_1 + +// The second good class also demonstrates the correct way to initialize +// base classes with other subobjects. This class uses the other helpers +// in the library, and shows the technique of using two base subobjects +// of the "same" type. +class good_class_2 + : private boost::base_from_member<base_or_member, 0> + , private boost::base_from_member<base_or_member, 1> + , private boost::base_from_member<base_or_member, 2> + , public base_class +{ + typedef boost::base_from_member<base_or_member, 0> pbase_type0; + typedef boost::base_from_member<base_or_member, 1> pbase_type1; + typedef boost::base_from_member<base_or_member, 2> pbase_type2; + typedef base_class base_type; + +public: + good_class_2(); + ~good_class_2(); + +}; // good_class_2 + +// Declare/define the single object registrar +object_registrar obj_reg; + + +// Main functionality +int +main() +{ + BOOST_TEST( obj_reg.db_.empty() ); + BOOST_TEST( obj_reg.defrauders_in_.empty() ); + BOOST_TEST( obj_reg.defrauders_out_.empty() ); + BOOST_TEST( obj_reg.overeager_.empty() ); + BOOST_TEST( obj_reg.overkilled_.empty() ); + + // Make a separate block to examine pre- and post-effects + { + using std::cout; + using std::endl; + + bad_class bc; + BOOST_TEST( obj_reg.db_.size() == 3 ); + BOOST_TEST( obj_reg.defrauders_in_.size() == 1 ); + + good_class_1 gc1; + BOOST_TEST( obj_reg.db_.size() == 6 ); + BOOST_TEST( obj_reg.defrauders_in_.size() == 1 ); + + good_class_2 gc2; + BOOST_TEST( obj_reg.db_.size() == 11 ); + BOOST_TEST( obj_reg.defrauders_in_.size() == 1 ); + + BOOST_TEST( obj_reg.defrauders_out_.empty() ); + BOOST_TEST( obj_reg.overeager_.empty() ); + BOOST_TEST( obj_reg.overkilled_.empty() ); + + // Getting the addresses of the objects ensure + // that they're used, and not optimized away. + cout << "Object 'bc' is at " << &bc << '.' << endl; + cout << "Object 'gc1' is at " << &gc1 << '.' << endl; + cout << "Object 'gc2' is at " << &gc2 << '.' << endl; + } + + BOOST_TEST( obj_reg.db_.empty() ); + BOOST_TEST( obj_reg.defrauders_in_.size() == 1 ); + BOOST_TEST( obj_reg.defrauders_out_.size() == 1 ); + BOOST_TEST( obj_reg.overeager_.empty() ); + BOOST_TEST( obj_reg.overkilled_.empty() ); + + return boost::report_errors(); +} + + +// Print an object's ID +std::ostream & +operator << +( + std::ostream & os, + object_id const & oi +) +{ + // I had an std::ostringstream to help, but I did not need it since + // the program never screws around with formatting. Worse, using + // std::ostringstream is an issue with some compilers. + + return os << '[' << ( oi.second ? oi.second->name() : "NOTHING" ) + << " at " << oi.first << ']'; +} + +// Get an object ID given an object +template < typename T > +inline +object_id +identify +( + T & obj +) +{ + return std::make_pair( static_cast<void *>(&obj), &(typeid( obj )) ); +} + +// Compare two object IDs +bool +object_id_compare::operator () +( + object_id const & a, + object_id const & b +) const +{ + std::less<void *> vp_cmp; + if ( vp_cmp(a.first, b.first) ) + { + return true; + } + else if ( vp_cmp(b.first, a.first) ) + { + return false; + } + else + { + // object pointers are equal, compare the types + if ( a.second == b.second ) + { + return false; + } + else if ( !a.second ) + { + return true; // NULL preceeds anything else + } + else if ( !b.second ) + { + return false; // NULL preceeds anything else + } + else + { + return a.second->before( *b.second ) != 0; + } + } +} + +// Let an object register its existence +void +object_registrar::register_object_imp +( + object_id obj +) +{ + if ( db_.count(obj) <= 0 ) + { + db_.insert( obj ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Registered " << obj << '.' << std::endl; + #endif + } + else + { + overeager_.push_back( obj ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Attempted to register a non-existant " << obj + << '.' << std::endl; + #endif + } +} + +// Let an object register its use of another object +void +object_registrar::register_use_imp +( + object_id owner, + object_id owned +) +{ + if ( db_.count(owned) > 0 ) + { + // We don't care to record usage registrations + } + else + { + defrauders_in_.push_back( std::make_pair(owner, owned) ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Attempted to own a non-existant " << owned + << " by " << owner << '.' << std::endl; + #endif + } +} + +// Let an object un-register its use of another object +void +object_registrar::unregister_use_imp +( + object_id owner, + object_id owned +) +{ + if ( db_.count(owned) > 0 ) + { + // We don't care to record usage un-registrations + } + else + { + defrauders_out_.push_back( std::make_pair(owner, owned) ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Attempted to disown a non-existant " << owned + << " by " << owner << '.' << std::endl; + #endif + } +} + +// Let an object un-register its existence +void +object_registrar::unregister_object_imp +( + object_id obj +) +{ + set_type::iterator const i = db_.find( obj ); + + if ( i != db_.end() ) + { + db_.erase( i ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Unregistered " << obj << '.' << std::endl; + #endif + } + else + { + overkilled_.push_back( obj ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Attempted to unregister a non-existant " << obj + << '.' << std::endl; + #endif + } +} + +// Macros to abstract the registration of objects +#ifndef BOOST_NO_MEMBER_TEMPLATES +#define PRIVATE_REGISTER_BIRTH(o) obj_reg.register_object( (o) ) +#define PRIVATE_REGISTER_DEATH(o) obj_reg.unregister_object( (o) ) +#define PRIVATE_REGISTER_USE(o, w) obj_reg.register_use( (o), (w) ) +#define PRIVATE_UNREGISTER_USE(o, w) obj_reg.unregister_use( (o), (w) ) +#else +#define PRIVATE_REGISTER_BIRTH(o) obj_reg.register_object_imp( \ + identify((o)) ) +#define PRIVATE_REGISTER_DEATH(o) obj_reg.unregister_object_imp( \ + identify((o)) ) +#define PRIVATE_REGISTER_USE(o, w) obj_reg.register_use_imp( identify((o)), \ + identify((w)) ) +#define PRIVATE_UNREGISTER_USE(o, w) obj_reg.unregister_use_imp( \ + identify((o)), identify((w)) ) +#endif + +// Create a base_or_member, with arguments to simulate member initializations +base_or_member::base_or_member +( + int x, // = 1 + double y // = -0.25 +) +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy x-factor is " << x << " and my y-factor is " << y + << '.' << std::endl; + #endif +} + +// Destroy a base_or_member +inline +base_or_member::~base_or_member +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); +} + +// Create a base_class, registering any objects used +base_class::base_class +( + base_or_member & x, + base_or_member * y, // = 0 + base_or_member * z // = 0 +) + : x_( &x ), y_( y ), z_( z ) +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy x-factor is " << x_; + #endif + + PRIVATE_REGISTER_USE( *this, *x_ ); + + if ( y_ ) + { + #if CONTROL_EXTRA_PRINTING + std::cout << ", my y-factor is " << y_; + #endif + + PRIVATE_REGISTER_USE( *this, *y_ ); + } + + if ( z_ ) + { + #if CONTROL_EXTRA_PRINTING + std::cout << ", my z-factor is " << z_; + #endif + + PRIVATE_REGISTER_USE( *this, *z_ ); + } + + #if CONTROL_EXTRA_PRINTING + std::cout << '.' << std::endl; + #endif +} + +// Destroy a base_class, unregistering the objects it uses +base_class::~base_class +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy x-factor was " << x_; + #endif + + PRIVATE_UNREGISTER_USE( *this, *x_ ); + + if ( y_ ) + { + #if CONTROL_EXTRA_PRINTING + std::cout << ", my y-factor was " << y_; + #endif + + PRIVATE_UNREGISTER_USE( *this, *y_ ); + } + + if ( z_ ) + { + #if CONTROL_EXTRA_PRINTING + std::cout << ", my z-factor was " << z_; + #endif + + PRIVATE_UNREGISTER_USE( *this, *z_ ); + } + + #if CONTROL_EXTRA_PRINTING + std::cout << '.' << std::endl; + #endif +} + +// Create a bad_class, noting the improper construction order +bad_class::bad_class +( +) + : x_( -7, 16.75 ), base_class( x_ ) // this order doesn't matter +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factor is at " << &x_ + << " and my base is at " << static_cast<base_class *>(this) << '.' + << std::endl; + #endif +} + +// Destroy a bad_class, noting the improper destruction order +bad_class::~bad_class +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factor was at " << &x_ + << " and my base was at " << static_cast<base_class *>(this) + << '.' << std::endl; + #endif +} + +// Create a good_class_1, noting the proper construction order +good_class_1::good_class_1 +( +) + : pbase_type( 8 ), base_type( member ) +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factor is at " << &member + << " and my base is at " << static_cast<base_class *>(this) << '.' + << std::endl; + #endif +} + +// Destroy a good_class_1, noting the proper destruction order +good_class_1::~good_class_1 +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factor was at " << &member + << " and my base was at " << static_cast<base_class *>(this) + << '.' << std::endl; + #endif +} + +// Create a good_class_2, noting the proper construction order +good_class_2::good_class_2 +( +) + : pbase_type0(), pbase_type1(-16, 0.125), pbase_type2(2, -3) + , base_type( pbase_type1::member, &this->pbase_type0::member, + &this->pbase_type2::member ) +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factors are at " << &this->pbase_type0::member + << ", " << &this->pbase_type1::member << ", " + << &this->pbase_type2::member << ", and my base is at " + << static_cast<base_class *>(this) << '.' << std::endl; + #endif +} + +// Destroy a good_class_2, noting the proper destruction order +good_class_2::~good_class_2 +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factors were at " << &this->pbase_type0::member + << ", " << &this->pbase_type1::member << ", " + << &this->pbase_type2::member << ", and my base was at " + << static_cast<base_class *>(this) << '.' << std::endl; + #endif +} diff --git a/src/boost/libs/utility/test/binary_test.cpp b/src/boost/libs/utility/test/binary_test.cpp new file mode 100644 index 000000000..f39dc08fb --- /dev/null +++ b/src/boost/libs/utility/test/binary_test.cpp @@ -0,0 +1,647 @@ +/*============================================================================= + Copyright (c) 2006, 2007 Matthew Calabrese + + Use, modification and distribution is 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) +==============================================================================*/ + +#include <boost/core/lightweight_test.hpp> +#include <boost/utility/binary.hpp> +#include <algorithm> +#include <cstddef> + +#ifdef BOOST_MSVC +#pragma warning(disable:4996) // warning C4996: 'std::equal': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' +#endif + +/* +Note: This file tests every single valid bit-grouping on its own, and some + random combinations of bit-groupings. +*/ + +std::size_t const num_random_test_values = 32; + +// Note: These hex values should all correspond with the binary array below +unsigned int const random_unsigned_ints_hex[num_random_test_values] + = { 0x0103u, 0x77ebu, 0x5f36u, 0x1f18u, 0xc530u, 0xa73au, 0xd6f8u, 0x0919u + , 0xfbb0u, 0x3e7cu, 0xd0e9u, 0x22c8u, 0x724eu, 0x14fau, 0xd98eu, 0x40b5 + , 0xeba0u, 0xfe50u, 0x688au, 0x1b05u, 0x5f9cu, 0xe4fcu, 0xa7b8u, 0xd3acu + , 0x1dddu, 0xbf04u, 0x8352u, 0xe89cu, 0x7506u, 0xe767u, 0xf489u, 0xe167 + }; + +unsigned int const random_unsigned_ints_binary[num_random_test_values] + = { BOOST_BINARY( 0 00010000 0011 ), BOOST_BINARY( 0 11101 1111 101011 ) + , BOOST_BINARY( 010111 1100110 1 1 0 ), BOOST_BINARY( 000 1 11110 00 11000 ) + , BOOST_BINARY( 110 001010 0110 000 ), BOOST_BINARY( 1010 01110011 1010 ) + , BOOST_BINARY( 11 010 1 101111 1000 ), BOOST_BINARY( 0000 100100 0110 01 ) + , BOOST_BINARY( 1111 101110 11 0000 ), BOOST_BINARY( 00111110 01111100 ) + , BOOST_BINARY( 11 010 000111 01001 ), BOOST_BINARY( 00100 010110 01000 ) + , BOOST_BINARY( 01 11001001 001110 ), BOOST_BINARY( 0010 1001111 1010 ) + , BOOST_BINARY( 1101 1 00110 0 01110 ), BOOST_BINARY( 100 000 01011010 1 ) + , BOOST_BINARY( 11 1010 1110 1000 00 ), BOOST_BINARY( 11111 110010 10000 ) + , BOOST_BINARY( 01101 00010 001010 ), BOOST_BINARY( 000 11011 000001 01 ) + , BOOST_BINARY( 01 01111 1100111 00 ), BOOST_BINARY( 1 110010 0111111 00 ) + , BOOST_BINARY( 101 0011 11 01110 00 ), BOOST_BINARY( 110100 1 110101 100 ) + , BOOST_BINARY( 00 1110111 011 101 ), BOOST_BINARY( 1011 1111 00000 100 ) + , BOOST_BINARY( 1000 00110 101 0010 ), BOOST_BINARY( 1110 10001 001110 0 ) + , BOOST_BINARY( 011 1010100 000 110 ), BOOST_BINARY( 1110 0111 01100 111 ) + , BOOST_BINARY( 11110 10010 001001 ), BOOST_BINARY( 11 1000010 1100 111 ) + }; + +unsigned int const unsigned_ints_1_bit[2] = +{ BOOST_BINARY( 0 ) +, BOOST_BINARY( 1 ) +}; + +unsigned int const unsigned_ints_2_bits[4] = +{ BOOST_BINARY( 00 ) +, BOOST_BINARY( 01 ) +, BOOST_BINARY( 10 ) +, BOOST_BINARY( 11 ) +}; + +unsigned int const unsigned_ints_3_bits[8] = +{ BOOST_BINARY( 000 ) +, BOOST_BINARY( 001 ) +, BOOST_BINARY( 010 ) +, BOOST_BINARY( 011 ) +, BOOST_BINARY( 100 ) +, BOOST_BINARY( 101 ) +, BOOST_BINARY( 110 ) +, BOOST_BINARY( 111 ) +}; + +unsigned int const unsigned_ints_4_bits[16] = +{ BOOST_BINARY( 0000 ) +, BOOST_BINARY( 0001 ) +, BOOST_BINARY( 0010 ) +, BOOST_BINARY( 0011 ) +, BOOST_BINARY( 0100 ) +, BOOST_BINARY( 0101 ) +, BOOST_BINARY( 0110 ) +, BOOST_BINARY( 0111 ) +, BOOST_BINARY( 1000 ) +, BOOST_BINARY( 1001 ) +, BOOST_BINARY( 1010 ) +, BOOST_BINARY( 1011 ) +, BOOST_BINARY( 1100 ) +, BOOST_BINARY( 1101 ) +, BOOST_BINARY( 1110 ) +, BOOST_BINARY( 1111 ) +}; + +unsigned int const unsigned_ints_5_bits[32] = +{ BOOST_BINARY( 00000 ) +, BOOST_BINARY( 00001 ) +, BOOST_BINARY( 00010 ) +, BOOST_BINARY( 00011 ) +, BOOST_BINARY( 00100 ) +, BOOST_BINARY( 00101 ) +, BOOST_BINARY( 00110 ) +, BOOST_BINARY( 00111 ) +, BOOST_BINARY( 01000 ) +, BOOST_BINARY( 01001 ) +, BOOST_BINARY( 01010 ) +, BOOST_BINARY( 01011 ) +, BOOST_BINARY( 01100 ) +, BOOST_BINARY( 01101 ) +, BOOST_BINARY( 01110 ) +, BOOST_BINARY( 01111 ) +, BOOST_BINARY( 10000 ) +, BOOST_BINARY( 10001 ) +, BOOST_BINARY( 10010 ) +, BOOST_BINARY( 10011 ) +, BOOST_BINARY( 10100 ) +, BOOST_BINARY( 10101 ) +, BOOST_BINARY( 10110 ) +, BOOST_BINARY( 10111 ) +, BOOST_BINARY( 11000 ) +, BOOST_BINARY( 11001 ) +, BOOST_BINARY( 11010 ) +, BOOST_BINARY( 11011 ) +, BOOST_BINARY( 11100 ) +, BOOST_BINARY( 11101 ) +, BOOST_BINARY( 11110 ) +, BOOST_BINARY( 11111 ) +}; + +unsigned int const unsigned_ints_6_bits[64] = +{ BOOST_BINARY( 000000 ) +, BOOST_BINARY( 000001 ) +, BOOST_BINARY( 000010 ) +, BOOST_BINARY( 000011 ) +, BOOST_BINARY( 000100 ) +, BOOST_BINARY( 000101 ) +, BOOST_BINARY( 000110 ) +, BOOST_BINARY( 000111 ) +, BOOST_BINARY( 001000 ) +, BOOST_BINARY( 001001 ) +, BOOST_BINARY( 001010 ) +, BOOST_BINARY( 001011 ) +, BOOST_BINARY( 001100 ) +, BOOST_BINARY( 001101 ) +, BOOST_BINARY( 001110 ) +, BOOST_BINARY( 001111 ) +, BOOST_BINARY( 010000 ) +, BOOST_BINARY( 010001 ) +, BOOST_BINARY( 010010 ) +, BOOST_BINARY( 010011 ) +, BOOST_BINARY( 010100 ) +, BOOST_BINARY( 010101 ) +, BOOST_BINARY( 010110 ) +, BOOST_BINARY( 010111 ) +, BOOST_BINARY( 011000 ) +, BOOST_BINARY( 011001 ) +, BOOST_BINARY( 011010 ) +, BOOST_BINARY( 011011 ) +, BOOST_BINARY( 011100 ) +, BOOST_BINARY( 011101 ) +, BOOST_BINARY( 011110 ) +, BOOST_BINARY( 011111 ) +, BOOST_BINARY( 100000 ) +, BOOST_BINARY( 100001 ) +, BOOST_BINARY( 100010 ) +, BOOST_BINARY( 100011 ) +, BOOST_BINARY( 100100 ) +, BOOST_BINARY( 100101 ) +, BOOST_BINARY( 100110 ) +, BOOST_BINARY( 100111 ) +, BOOST_BINARY( 101000 ) +, BOOST_BINARY( 101001 ) +, BOOST_BINARY( 101010 ) +, BOOST_BINARY( 101011 ) +, BOOST_BINARY( 101100 ) +, BOOST_BINARY( 101101 ) +, BOOST_BINARY( 101110 ) +, BOOST_BINARY( 101111 ) +, BOOST_BINARY( 110000 ) +, BOOST_BINARY( 110001 ) +, BOOST_BINARY( 110010 ) +, BOOST_BINARY( 110011 ) +, BOOST_BINARY( 110100 ) +, BOOST_BINARY( 110101 ) +, BOOST_BINARY( 110110 ) +, BOOST_BINARY( 110111 ) +, BOOST_BINARY( 111000 ) +, BOOST_BINARY( 111001 ) +, BOOST_BINARY( 111010 ) +, BOOST_BINARY( 111011 ) +, BOOST_BINARY( 111100 ) +, BOOST_BINARY( 111101 ) +, BOOST_BINARY( 111110 ) +, BOOST_BINARY( 111111 ) +}; + +unsigned int const unsigned_ints_7_bits[128] = +{ BOOST_BINARY( 0000000 ) +, BOOST_BINARY( 0000001 ) +, BOOST_BINARY( 0000010 ) +, BOOST_BINARY( 0000011 ) +, BOOST_BINARY( 0000100 ) +, BOOST_BINARY( 0000101 ) +, BOOST_BINARY( 0000110 ) +, BOOST_BINARY( 0000111 ) +, BOOST_BINARY( 0001000 ) +, BOOST_BINARY( 0001001 ) +, BOOST_BINARY( 0001010 ) +, BOOST_BINARY( 0001011 ) +, BOOST_BINARY( 0001100 ) +, BOOST_BINARY( 0001101 ) +, BOOST_BINARY( 0001110 ) +, BOOST_BINARY( 0001111 ) +, BOOST_BINARY( 0010000 ) +, BOOST_BINARY( 0010001 ) +, BOOST_BINARY( 0010010 ) +, BOOST_BINARY( 0010011 ) +, BOOST_BINARY( 0010100 ) +, BOOST_BINARY( 0010101 ) +, BOOST_BINARY( 0010110 ) +, BOOST_BINARY( 0010111 ) +, BOOST_BINARY( 0011000 ) +, BOOST_BINARY( 0011001 ) +, BOOST_BINARY( 0011010 ) +, BOOST_BINARY( 0011011 ) +, BOOST_BINARY( 0011100 ) +, BOOST_BINARY( 0011101 ) +, BOOST_BINARY( 0011110 ) +, BOOST_BINARY( 0011111 ) +, BOOST_BINARY( 0100000 ) +, BOOST_BINARY( 0100001 ) +, BOOST_BINARY( 0100010 ) +, BOOST_BINARY( 0100011 ) +, BOOST_BINARY( 0100100 ) +, BOOST_BINARY( 0100101 ) +, BOOST_BINARY( 0100110 ) +, BOOST_BINARY( 0100111 ) +, BOOST_BINARY( 0101000 ) +, BOOST_BINARY( 0101001 ) +, BOOST_BINARY( 0101010 ) +, BOOST_BINARY( 0101011 ) +, BOOST_BINARY( 0101100 ) +, BOOST_BINARY( 0101101 ) +, BOOST_BINARY( 0101110 ) +, BOOST_BINARY( 0101111 ) +, BOOST_BINARY( 0110000 ) +, BOOST_BINARY( 0110001 ) +, BOOST_BINARY( 0110010 ) +, BOOST_BINARY( 0110011 ) +, BOOST_BINARY( 0110100 ) +, BOOST_BINARY( 0110101 ) +, BOOST_BINARY( 0110110 ) +, BOOST_BINARY( 0110111 ) +, BOOST_BINARY( 0111000 ) +, BOOST_BINARY( 0111001 ) +, BOOST_BINARY( 0111010 ) +, BOOST_BINARY( 0111011 ) +, BOOST_BINARY( 0111100 ) +, BOOST_BINARY( 0111101 ) +, BOOST_BINARY( 0111110 ) +, BOOST_BINARY( 0111111 ) +, BOOST_BINARY( 1000000 ) +, BOOST_BINARY( 1000001 ) +, BOOST_BINARY( 1000010 ) +, BOOST_BINARY( 1000011 ) +, BOOST_BINARY( 1000100 ) +, BOOST_BINARY( 1000101 ) +, BOOST_BINARY( 1000110 ) +, BOOST_BINARY( 1000111 ) +, BOOST_BINARY( 1001000 ) +, BOOST_BINARY( 1001001 ) +, BOOST_BINARY( 1001010 ) +, BOOST_BINARY( 1001011 ) +, BOOST_BINARY( 1001100 ) +, BOOST_BINARY( 1001101 ) +, BOOST_BINARY( 1001110 ) +, BOOST_BINARY( 1001111 ) +, BOOST_BINARY( 1010000 ) +, BOOST_BINARY( 1010001 ) +, BOOST_BINARY( 1010010 ) +, BOOST_BINARY( 1010011 ) +, BOOST_BINARY( 1010100 ) +, BOOST_BINARY( 1010101 ) +, BOOST_BINARY( 1010110 ) +, BOOST_BINARY( 1010111 ) +, BOOST_BINARY( 1011000 ) +, BOOST_BINARY( 1011001 ) +, BOOST_BINARY( 1011010 ) +, BOOST_BINARY( 1011011 ) +, BOOST_BINARY( 1011100 ) +, BOOST_BINARY( 1011101 ) +, BOOST_BINARY( 1011110 ) +, BOOST_BINARY( 1011111 ) +, BOOST_BINARY( 1100000 ) +, BOOST_BINARY( 1100001 ) +, BOOST_BINARY( 1100010 ) +, BOOST_BINARY( 1100011 ) +, BOOST_BINARY( 1100100 ) +, BOOST_BINARY( 1100101 ) +, BOOST_BINARY( 1100110 ) +, BOOST_BINARY( 1100111 ) +, BOOST_BINARY( 1101000 ) +, BOOST_BINARY( 1101001 ) +, BOOST_BINARY( 1101010 ) +, BOOST_BINARY( 1101011 ) +, BOOST_BINARY( 1101100 ) +, BOOST_BINARY( 1101101 ) +, BOOST_BINARY( 1101110 ) +, BOOST_BINARY( 1101111 ) +, BOOST_BINARY( 1110000 ) +, BOOST_BINARY( 1110001 ) +, BOOST_BINARY( 1110010 ) +, BOOST_BINARY( 1110011 ) +, BOOST_BINARY( 1110100 ) +, BOOST_BINARY( 1110101 ) +, BOOST_BINARY( 1110110 ) +, BOOST_BINARY( 1110111 ) +, BOOST_BINARY( 1111000 ) +, BOOST_BINARY( 1111001 ) +, BOOST_BINARY( 1111010 ) +, BOOST_BINARY( 1111011 ) +, BOOST_BINARY( 1111100 ) +, BOOST_BINARY( 1111101 ) +, BOOST_BINARY( 1111110 ) +, BOOST_BINARY( 1111111 ) +}; +unsigned int const unsigned_ints_8_bits[256] = +{ BOOST_BINARY( 00000000 ) +, BOOST_BINARY( 00000001 ) +, BOOST_BINARY( 00000010 ) +, BOOST_BINARY( 00000011 ) +, BOOST_BINARY( 00000100 ) +, BOOST_BINARY( 00000101 ) +, BOOST_BINARY( 00000110 ) +, BOOST_BINARY( 00000111 ) +, BOOST_BINARY( 00001000 ) +, BOOST_BINARY( 00001001 ) +, BOOST_BINARY( 00001010 ) +, BOOST_BINARY( 00001011 ) +, BOOST_BINARY( 00001100 ) +, BOOST_BINARY( 00001101 ) +, BOOST_BINARY( 00001110 ) +, BOOST_BINARY( 00001111 ) +, BOOST_BINARY( 00010000 ) +, BOOST_BINARY( 00010001 ) +, BOOST_BINARY( 00010010 ) +, BOOST_BINARY( 00010011 ) +, BOOST_BINARY( 00010100 ) +, BOOST_BINARY( 00010101 ) +, BOOST_BINARY( 00010110 ) +, BOOST_BINARY( 00010111 ) +, BOOST_BINARY( 00011000 ) +, BOOST_BINARY( 00011001 ) +, BOOST_BINARY( 00011010 ) +, BOOST_BINARY( 00011011 ) +, BOOST_BINARY( 00011100 ) +, BOOST_BINARY( 00011101 ) +, BOOST_BINARY( 00011110 ) +, BOOST_BINARY( 00011111 ) +, BOOST_BINARY( 00100000 ) +, BOOST_BINARY( 00100001 ) +, BOOST_BINARY( 00100010 ) +, BOOST_BINARY( 00100011 ) +, BOOST_BINARY( 00100100 ) +, BOOST_BINARY( 00100101 ) +, BOOST_BINARY( 00100110 ) +, BOOST_BINARY( 00100111 ) +, BOOST_BINARY( 00101000 ) +, BOOST_BINARY( 00101001 ) +, BOOST_BINARY( 00101010 ) +, BOOST_BINARY( 00101011 ) +, BOOST_BINARY( 00101100 ) +, BOOST_BINARY( 00101101 ) +, BOOST_BINARY( 00101110 ) +, BOOST_BINARY( 00101111 ) +, BOOST_BINARY( 00110000 ) +, BOOST_BINARY( 00110001 ) +, BOOST_BINARY( 00110010 ) +, BOOST_BINARY( 00110011 ) +, BOOST_BINARY( 00110100 ) +, BOOST_BINARY( 00110101 ) +, BOOST_BINARY( 00110110 ) +, BOOST_BINARY( 00110111 ) +, BOOST_BINARY( 00111000 ) +, BOOST_BINARY( 00111001 ) +, BOOST_BINARY( 00111010 ) +, BOOST_BINARY( 00111011 ) +, BOOST_BINARY( 00111100 ) +, BOOST_BINARY( 00111101 ) +, BOOST_BINARY( 00111110 ) +, BOOST_BINARY( 00111111 ) +, BOOST_BINARY( 01000000 ) +, BOOST_BINARY( 01000001 ) +, BOOST_BINARY( 01000010 ) +, BOOST_BINARY( 01000011 ) +, BOOST_BINARY( 01000100 ) +, BOOST_BINARY( 01000101 ) +, BOOST_BINARY( 01000110 ) +, BOOST_BINARY( 01000111 ) +, BOOST_BINARY( 01001000 ) +, BOOST_BINARY( 01001001 ) +, BOOST_BINARY( 01001010 ) +, BOOST_BINARY( 01001011 ) +, BOOST_BINARY( 01001100 ) +, BOOST_BINARY( 01001101 ) +, BOOST_BINARY( 01001110 ) +, BOOST_BINARY( 01001111 ) +, BOOST_BINARY( 01010000 ) +, BOOST_BINARY( 01010001 ) +, BOOST_BINARY( 01010010 ) +, BOOST_BINARY( 01010011 ) +, BOOST_BINARY( 01010100 ) +, BOOST_BINARY( 01010101 ) +, BOOST_BINARY( 01010110 ) +, BOOST_BINARY( 01010111 ) +, BOOST_BINARY( 01011000 ) +, BOOST_BINARY( 01011001 ) +, BOOST_BINARY( 01011010 ) +, BOOST_BINARY( 01011011 ) +, BOOST_BINARY( 01011100 ) +, BOOST_BINARY( 01011101 ) +, BOOST_BINARY( 01011110 ) +, BOOST_BINARY( 01011111 ) +, BOOST_BINARY( 01100000 ) +, BOOST_BINARY( 01100001 ) +, BOOST_BINARY( 01100010 ) +, BOOST_BINARY( 01100011 ) +, BOOST_BINARY( 01100100 ) +, BOOST_BINARY( 01100101 ) +, BOOST_BINARY( 01100110 ) +, BOOST_BINARY( 01100111 ) +, BOOST_BINARY( 01101000 ) +, BOOST_BINARY( 01101001 ) +, BOOST_BINARY( 01101010 ) +, BOOST_BINARY( 01101011 ) +, BOOST_BINARY( 01101100 ) +, BOOST_BINARY( 01101101 ) +, BOOST_BINARY( 01101110 ) +, BOOST_BINARY( 01101111 ) +, BOOST_BINARY( 01110000 ) +, BOOST_BINARY( 01110001 ) +, BOOST_BINARY( 01110010 ) +, BOOST_BINARY( 01110011 ) +, BOOST_BINARY( 01110100 ) +, BOOST_BINARY( 01110101 ) +, BOOST_BINARY( 01110110 ) +, BOOST_BINARY( 01110111 ) +, BOOST_BINARY( 01111000 ) +, BOOST_BINARY( 01111001 ) +, BOOST_BINARY( 01111010 ) +, BOOST_BINARY( 01111011 ) +, BOOST_BINARY( 01111100 ) +, BOOST_BINARY( 01111101 ) +, BOOST_BINARY( 01111110 ) +, BOOST_BINARY( 01111111 ) +, BOOST_BINARY( 10000000 ) +, BOOST_BINARY( 10000001 ) +, BOOST_BINARY( 10000010 ) +, BOOST_BINARY( 10000011 ) +, BOOST_BINARY( 10000100 ) +, BOOST_BINARY( 10000101 ) +, BOOST_BINARY( 10000110 ) +, BOOST_BINARY( 10000111 ) +, BOOST_BINARY( 10001000 ) +, BOOST_BINARY( 10001001 ) +, BOOST_BINARY( 10001010 ) +, BOOST_BINARY( 10001011 ) +, BOOST_BINARY( 10001100 ) +, BOOST_BINARY( 10001101 ) +, BOOST_BINARY( 10001110 ) +, BOOST_BINARY( 10001111 ) +, BOOST_BINARY( 10010000 ) +, BOOST_BINARY( 10010001 ) +, BOOST_BINARY( 10010010 ) +, BOOST_BINARY( 10010011 ) +, BOOST_BINARY( 10010100 ) +, BOOST_BINARY( 10010101 ) +, BOOST_BINARY( 10010110 ) +, BOOST_BINARY( 10010111 ) +, BOOST_BINARY( 10011000 ) +, BOOST_BINARY( 10011001 ) +, BOOST_BINARY( 10011010 ) +, BOOST_BINARY( 10011011 ) +, BOOST_BINARY( 10011100 ) +, BOOST_BINARY( 10011101 ) +, BOOST_BINARY( 10011110 ) +, BOOST_BINARY( 10011111 ) +, BOOST_BINARY( 10100000 ) +, BOOST_BINARY( 10100001 ) +, BOOST_BINARY( 10100010 ) +, BOOST_BINARY( 10100011 ) +, BOOST_BINARY( 10100100 ) +, BOOST_BINARY( 10100101 ) +, BOOST_BINARY( 10100110 ) +, BOOST_BINARY( 10100111 ) +, BOOST_BINARY( 10101000 ) +, BOOST_BINARY( 10101001 ) +, BOOST_BINARY( 10101010 ) +, BOOST_BINARY( 10101011 ) +, BOOST_BINARY( 10101100 ) +, BOOST_BINARY( 10101101 ) +, BOOST_BINARY( 10101110 ) +, BOOST_BINARY( 10101111 ) +, BOOST_BINARY( 10110000 ) +, BOOST_BINARY( 10110001 ) +, BOOST_BINARY( 10110010 ) +, BOOST_BINARY( 10110011 ) +, BOOST_BINARY( 10110100 ) +, BOOST_BINARY( 10110101 ) +, BOOST_BINARY( 10110110 ) +, BOOST_BINARY( 10110111 ) +, BOOST_BINARY( 10111000 ) +, BOOST_BINARY( 10111001 ) +, BOOST_BINARY( 10111010 ) +, BOOST_BINARY( 10111011 ) +, BOOST_BINARY( 10111100 ) +, BOOST_BINARY( 10111101 ) +, BOOST_BINARY( 10111110 ) +, BOOST_BINARY( 10111111 ) +, BOOST_BINARY( 11000000 ) +, BOOST_BINARY( 11000001 ) +, BOOST_BINARY( 11000010 ) +, BOOST_BINARY( 11000011 ) +, BOOST_BINARY( 11000100 ) +, BOOST_BINARY( 11000101 ) +, BOOST_BINARY( 11000110 ) +, BOOST_BINARY( 11000111 ) +, BOOST_BINARY( 11001000 ) +, BOOST_BINARY( 11001001 ) +, BOOST_BINARY( 11001010 ) +, BOOST_BINARY( 11001011 ) +, BOOST_BINARY( 11001100 ) +, BOOST_BINARY( 11001101 ) +, BOOST_BINARY( 11001110 ) +, BOOST_BINARY( 11001111 ) +, BOOST_BINARY( 11010000 ) +, BOOST_BINARY( 11010001 ) +, BOOST_BINARY( 11010010 ) +, BOOST_BINARY( 11010011 ) +, BOOST_BINARY( 11010100 ) +, BOOST_BINARY( 11010101 ) +, BOOST_BINARY( 11010110 ) +, BOOST_BINARY( 11010111 ) +, BOOST_BINARY( 11011000 ) +, BOOST_BINARY( 11011001 ) +, BOOST_BINARY( 11011010 ) +, BOOST_BINARY( 11011011 ) +, BOOST_BINARY( 11011100 ) +, BOOST_BINARY( 11011101 ) +, BOOST_BINARY( 11011110 ) +, BOOST_BINARY( 11011111 ) +, BOOST_BINARY( 11100000 ) +, BOOST_BINARY( 11100001 ) +, BOOST_BINARY( 11100010 ) +, BOOST_BINARY( 11100011 ) +, BOOST_BINARY( 11100100 ) +, BOOST_BINARY( 11100101 ) +, BOOST_BINARY( 11100110 ) +, BOOST_BINARY( 11100111 ) +, BOOST_BINARY( 11101000 ) +, BOOST_BINARY( 11101001 ) +, BOOST_BINARY( 11101010 ) +, BOOST_BINARY( 11101011 ) +, BOOST_BINARY( 11101100 ) +, BOOST_BINARY( 11101101 ) +, BOOST_BINARY( 11101110 ) +, BOOST_BINARY( 11101111 ) +, BOOST_BINARY( 11110000 ) +, BOOST_BINARY( 11110001 ) +, BOOST_BINARY( 11110010 ) +, BOOST_BINARY( 11110011 ) +, BOOST_BINARY( 11110100 ) +, BOOST_BINARY( 11110101 ) +, BOOST_BINARY( 11110110 ) +, BOOST_BINARY( 11110111 ) +, BOOST_BINARY( 11111000 ) +, BOOST_BINARY( 11111001 ) +, BOOST_BINARY( 11111010 ) +, BOOST_BINARY( 11111011 ) +, BOOST_BINARY( 11111100 ) +, BOOST_BINARY( 11111101 ) +, BOOST_BINARY( 11111110 ) +, BOOST_BINARY( 11111111 ) +}; + +struct left_is_not_one_less_than_right +{ + bool operator ()( unsigned int left, unsigned int right ) const + { + return right != left + 1; + } +}; + +template< std::size_t Size > +bool is_ascending_from_0_array( unsigned int const (&array)[Size] ) +{ + unsigned int const* const curr = array, + * const end = array + Size; + + return ( *curr == 0 ) + && ( std::adjacent_find( curr, end + , left_is_not_one_less_than_right() + ) + == end + ); +} + +std::size_t const unsigned_int_id = 1, + unsigned_long_int_id = 2; + +typedef char (&unsigned_int_id_type)[unsigned_int_id]; +typedef char (&unsigned_long_int_id_type)[unsigned_long_int_id]; + +// Note: Functions only used for type checking +unsigned_int_id_type binary_type_checker( unsigned int ); +unsigned_long_int_id_type binary_type_checker( unsigned long int ); + +int main() +{ + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_1_bit ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_2_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_3_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_4_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_5_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_6_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_7_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_8_bits ) ); + + BOOST_TEST( std::equal( &random_unsigned_ints_hex[0] + , random_unsigned_ints_hex + num_random_test_values + , &random_unsigned_ints_binary[0] + ) + ); + + BOOST_TEST( sizeof( binary_type_checker( BOOST_BINARY_U( 110100 1010 ) ) ) + == unsigned_int_id + ); + + BOOST_TEST( sizeof( binary_type_checker( BOOST_BINARY_UL( 11110 ) ) ) + == unsigned_long_int_id + ); + + BOOST_TEST( sizeof( binary_type_checker( BOOST_BINARY_LU( 10 0001 ) ) ) + == unsigned_long_int_id + ); + + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/call_traits_test.cpp b/src/boost/libs/utility/test/call_traits_test.cpp new file mode 100644 index 000000000..9e49b68a4 --- /dev/null +++ b/src/boost/libs/utility/test/call_traits_test.cpp @@ -0,0 +1,418 @@ +// boost::compressed_pair test program + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + + +// standalone test program for <boost/call_traits.hpp> +// 18 Mar 2002: +// Changed some names to prevent conflicts with some new type_traits additions. +// 03 Oct 2000: +// Enabled extra tests for VC6. + +#include <iostream> +#include <iomanip> +#include <algorithm> +#include <typeinfo> +#include <boost/call_traits.hpp> + +#include <libs/type_traits/test/test.hpp> +#include <libs/type_traits/test/check_type.hpp> + +#ifdef BOOST_MSVC +#pragma warning(disable:4181) // : warning C4181: qualifier applied to reference type; ignored +#endif + +// a way prevent warnings for unused variables +template<class T> inline void unused_variable(const T&) {} + +// +// struct contained models a type that contains a type (for example std::pair) +// arrays are contained by value, and have to be treated as a special case: +// +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()const { return v_; } + // return by_ref: + reference get() { return v_; } + const_reference const_get()const { return v_; } + // pass value: + void call(param_type){} +private: + contained& operator=(const contained&); +}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template <class T, std::size_t N> +struct contained<T[N]> +{ + typedef typename boost::call_traits<T[N]>::param_type param_type; + typedef typename boost::call_traits<T[N]>::reference reference; + typedef typename boost::call_traits<T[N]>::const_reference const_reference; + typedef T value_type[N]; + typedef typename boost::call_traits<T[N]>::value_type result_type; + + value_type v_; + + contained(param_type p) + { + std::copy(p, p+N, v_); + } + // return byval: + result_type value()const { return v_; } + // return by_ref: + reference get() { return v_; } + const_reference const_get()const { return v_; } + void call(param_type){} +private: + contained& operator=(const contained&); +}; +#endif + +template <class T> +contained<typename boost::call_traits<T>::value_type> test_wrap_type(const T& t) +{ + typedef typename boost::call_traits<T>::value_type ct; + return contained<ct>(t); +} + +namespace test{ + +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); +} + +} // namespace test + +using namespace std; + +// +// struct call_traits_checker: +// verifies behaviour of contained example: +// +template <class T> +struct call_traits_checker +{ + typedef typename boost::call_traits<T>::param_type param_type; + void operator()(param_type); +}; + +template <class T> +void call_traits_checker<T>::operator()(param_type p) +{ + T t(p); + contained<T> c(t); + cout << "checking contained<" << typeid(T).name() << ">..." << endl; + BOOST_CHECK(t == c.value()); + BOOST_CHECK(t == c.get()); + BOOST_CHECK(t == c.const_get()); +#ifndef __ICL + //cout << "typeof contained<" << typeid(T).name() << ">::v_ is: " << typeid(&contained<T>::v_).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::value() is: " << typeid(&contained<T>::value).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::get() is: " << typeid(&contained<T>::get).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::const_get() is: " << typeid(&contained<T>::const_get).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::call() is: " << typeid(&contained<T>::call).name() << endl; + cout << endl; +#endif +} + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template <class T, std::size_t N> +struct call_traits_checker<T[N]> +{ + typedef typename boost::call_traits<T[N]>::param_type param_type; + void operator()(param_type t) + { + contained<T[N]> c(t); + cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl; + unsigned int i = 0; + for(i = 0; i < N; ++i) + BOOST_CHECK(t[i] == c.value()[i]); + for(i = 0; i < N; ++i) + BOOST_CHECK(t[i] == c.get()[i]); + for(i = 0; i < N; ++i) + BOOST_CHECK(t[i] == c.const_get()[i]); + + cout << "typeof contained<" << typeid(T[N]).name() << ">::v_ is: " << typeid(&contained<T[N]>::v_).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::value is: " << typeid(&contained<T[N]>::value).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::get is: " << typeid(&contained<T[N]>::get).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is: " << typeid(&contained<T[N]>::const_get).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::call is: " << typeid(&contained<T[N]>::call).name() << endl; + cout << endl; + } +}; +#endif + +// +// check_wrap: +template <class W, class U> +void check_wrap(const W& w, const U& u) +{ + cout << "checking " << typeid(W).name() << "..." << endl; + BOOST_CHECK(w.value() == u); +} + +// +// check_make_pair: +// verifies behaviour of "make_pair": +// +template <class T, class U, class V> +void check_make_pair(T c, U u, V v) +{ + cout << "checking std::pair<" << typeid(c.first).name() << ", " << typeid(c.second).name() << ">..." << endl; + BOOST_CHECK(c.first == u); + BOOST_CHECK(c.second == v); + cout << endl; +} + + +struct comparible_UDT +{ + int i_; + comparible_UDT() : i_(2){} + comparible_UDT(const comparible_UDT& other) : i_(other.i_){} + comparible_UDT& operator=(const comparible_UDT& other) + { + i_ = other.i_; + return *this; + } + bool operator == (const comparible_UDT& v){ return v.i_ == i_; } +}; + +int main() +{ + call_traits_checker<comparible_UDT> c1; + comparible_UDT u; + c1(u); + call_traits_checker<int> c2; + call_traits_checker<enum_UDT> c2b; + int i = 2; + c2(i); + c2b(one); + int* pi = &i; + int a[2] = {1,2}; +#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL) + call_traits_checker<int*> c3; + c3(pi); + call_traits_checker<int&> c4; + c4(i); + call_traits_checker<const int&> c5; + c5(i); +#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC) + call_traits_checker<int[2]> c6; + c6(a); +#endif +#endif + + check_wrap(test_wrap_type(2), 2); +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) + check_wrap(test_wrap_type(a), a); + check_make_pair(test::make_pair(a, a), a, a); +#endif + + // cv-qualifiers applied to reference types should have no effect + // declare these here for later use with is_reference and remove_reference: + typedef int& r_type; + typedef const r_type cr_type; + + BOOST_CHECK_TYPE(comparible_UDT, boost::call_traits<comparible_UDT>::value_type); + BOOST_CHECK_TYPE(comparible_UDT&, boost::call_traits<comparible_UDT>::reference); + BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits<comparible_UDT>::const_reference); + BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits<comparible_UDT>::param_type); + BOOST_CHECK_TYPE(int, boost::call_traits<int>::value_type); + BOOST_CHECK_TYPE(int&, boost::call_traits<int>::reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits<int>::const_reference); + BOOST_CHECK_TYPE(const int, boost::call_traits<int>::param_type); + BOOST_CHECK_TYPE(int*, boost::call_traits<int*>::value_type); + BOOST_CHECK_TYPE(int*&, boost::call_traits<int*>::reference); + BOOST_CHECK_TYPE(int*const&, boost::call_traits<int*>::const_reference); + BOOST_CHECK_TYPE(int*const, boost::call_traits<int*>::param_type); +#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) + BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::value_type); + BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits<int&>::const_reference); + BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::param_type); +#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))) + BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::value_type); + BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits<cr_type>::const_reference); + BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::param_type); +#else + std::cout << "Your compiler cannot instantiate call_traits<int&const>, skipping four tests (4 errors)" << std::endl; +#endif + BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::value_type); + BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::const_reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::param_type); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_CHECK_TYPE(const int*, boost::call_traits<int[3]>::value_type); + BOOST_CHECK_TYPE(int(&)[3], boost::call_traits<int[3]>::reference); + BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<int[3]>::const_reference); + BOOST_CHECK_TYPE(const int*const, boost::call_traits<int[3]>::param_type); + BOOST_CHECK_TYPE(const int*, boost::call_traits<const int[3]>::value_type); + BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<const int[3]>::reference); + BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<const int[3]>::const_reference); + BOOST_CHECK_TYPE(const int*const, boost::call_traits<const int[3]>::param_type); + // test with abstract base class: + BOOST_CHECK_TYPE(test_abc1, boost::call_traits<test_abc1>::value_type); + BOOST_CHECK_TYPE(test_abc1&, boost::call_traits<test_abc1>::reference); + BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits<test_abc1>::const_reference); + BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits<test_abc1>::param_type); +#else + std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl; +#endif +#else + std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl; +#endif + // test with an incomplete type: + BOOST_CHECK_TYPE(incomplete_type, boost::call_traits<incomplete_type>::value_type); + BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits<incomplete_type>::reference); + BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference); + BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::param_type); + // test enum: + BOOST_CHECK_TYPE(enum_UDT, boost::call_traits<enum_UDT>::value_type); + BOOST_CHECK_TYPE(enum_UDT&, boost::call_traits<enum_UDT>::reference); + BOOST_CHECK_TYPE(const enum_UDT&, boost::call_traits<enum_UDT>::const_reference); + BOOST_CHECK_TYPE(const enum_UDT, boost::call_traits<enum_UDT>::param_type); + return 0; +} + +// +// define call_traits tests to check that the assertions in the docs do actually work +// this is an compile-time only set of tests: +// +template <typename T, bool isarray = false> +struct call_traits_test +{ + typedef ::boost::call_traits<T> ct; + typedef typename ct::param_type param_type; + typedef typename ct::reference reference; + typedef typename ct::const_reference const_reference; + typedef typename ct::value_type value_type; + static void assert_construct(param_type val); +}; + +template <typename T, bool isarray> +void call_traits_test<T, isarray>::assert_construct(typename call_traits_test<T, isarray>::param_type val) +{ + // + // this is to check that the call_traits assertions are valid: + T t(val); + value_type v(t); + reference r(t); + const_reference cr(t); + param_type p(t); + value_type v2(v); + value_type v3(r); + value_type v4(p); + reference r2(v); + reference r3(r); + const_reference cr2(v); + const_reference cr3(r); + const_reference cr4(cr); + const_reference cr5(p); + param_type p2(v); + param_type p3(r); + param_type p4(p); + + unused_variable(v2); + unused_variable(v3); + unused_variable(v4); + unused_variable(r2); + unused_variable(r3); + unused_variable(cr2); + unused_variable(cr3); + unused_variable(cr4); + unused_variable(cr5); + unused_variable(p2); + unused_variable(p3); + unused_variable(p4); +} +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template <typename T> +struct call_traits_test<T, true> +{ + typedef ::boost::call_traits<T> ct; + typedef typename ct::param_type param_type; + typedef typename ct::reference reference; + typedef typename ct::const_reference const_reference; + typedef typename ct::value_type value_type; + static void assert_construct(param_type val); +}; + +template <typename T> +void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>::param_type val) +{ + // + // this is to check that the call_traits assertions are valid: + T t; + value_type v(t); + value_type v5(val); + reference r = t; + const_reference cr = t; + reference r2 = r; + #ifndef __BORLANDC__ + // C++ Builder buglet: + const_reference cr2 = r; + #endif + param_type p(t); + value_type v2(v); + const_reference cr3 = cr; + value_type v3(r); + value_type v4(p); + param_type p2(v); + param_type p3(r); + param_type p4(p); + + unused_variable(v2); + unused_variable(v3); + unused_variable(v4); + unused_variable(v5); +#ifndef __BORLANDC__ + unused_variable(r2); + unused_variable(cr2); +#endif + unused_variable(cr3); + unused_variable(p2); + unused_variable(p3); + unused_variable(p4); +} +#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// +// now check call_traits assertions by instantiating call_traits_test: +template struct call_traits_test<int>; +template struct call_traits_test<const int>; +template struct call_traits_test<int*>; +#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) +template struct call_traits_test<int&>; +template struct call_traits_test<const int&>; +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) +template struct call_traits_test<int[2], true>; +#endif +#endif + diff --git a/src/boost/libs/utility/test/compressed_pair_final_test.cpp b/src/boost/libs/utility/test/compressed_pair_final_test.cpp new file mode 100644 index 000000000..247f3fceb --- /dev/null +++ b/src/boost/libs/utility/test/compressed_pair_final_test.cpp @@ -0,0 +1,55 @@ +/* +Copyright 2018 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include <boost/config.hpp> +#if !defined(BOOST_NO_CXX11_FINAL) +#include <boost/compressed_pair.hpp> +#include <boost/core/lightweight_test.hpp> + +struct type1 { + operator bool() const { + return false; + } +}; + +struct type2 final { + operator bool() const { + return false; + } +}; + +#if !defined(BOOST_IS_FINAL) +namespace boost { + +template<> +struct is_final<type2> + : true_type { }; + +} /* boost*/ +#endif + +template<class T1, class T2> +void test() +{ + boost::compressed_pair<T1, T2> p; + BOOST_TEST(!p.first()); + BOOST_TEST(!p.second()); +} + +int main() +{ + test<type1, type2>(); + test<type2, type1>(); + test<type2, type2>(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/utility/test/compressed_pair_test.cpp b/src/boost/libs/utility/test/compressed_pair_test.cpp new file mode 100644 index 000000000..ea10b2c0d --- /dev/null +++ b/src/boost/libs/utility/test/compressed_pair_test.cpp @@ -0,0 +1,387 @@ +// boost::compressed_pair test program + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +// standalone test program for <boost/compressed_pair.hpp> +// Revised 03 Oct 2000: +// Enabled tests for VC6. + +#include <iostream> +#include <typeinfo> +#include <cassert> + +#include <boost/compressed_pair.hpp> +#include <boost/core/lightweight_test.hpp> + +using namespace boost; + +struct empty_UDT +{ + ~empty_UDT(){}; + empty_UDT& operator=(const empty_UDT&){ return *this; } + bool operator==(const empty_UDT&)const + { return true; } +}; +struct empty_POD_UDT +{ + empty_POD_UDT& operator=(const empty_POD_UDT&){ return *this; } + bool operator==(const empty_POD_UDT&)const + { return true; } +}; + +struct non_empty1 +{ + int i; + non_empty1() : i(1){} + non_empty1(int v) : i(v){} + friend bool operator==(const non_empty1& a, const non_empty1& b) + { return a.i == b.i; } +}; + +struct non_empty2 +{ + int i; + non_empty2() : i(3){} + non_empty2(int v) : i(v){} + friend bool operator==(const non_empty2& a, const non_empty2& b) + { return a.i == b.i; } +}; + +#ifdef __GNUC__ +using std::swap; +#endif + +template <class T1, class T2> +struct compressed_pair_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits<first_type>::param_type first_param_type; + typedef typename call_traits<second_type>::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template <class T1, class T2> +void compressed_pair_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) +{ +#ifndef __GNUC__ + // gcc 2.90 can't cope with function scope using + // declarations, and generates an internal compiler error... + using std::swap; +#endif + // default construct: + boost::compressed_pair<T1,T2> cp1; + // first param construct: + boost::compressed_pair<T1,T2> cp2(p1); + cp2.second() = p2; + BOOST_TEST(cp2.first() == p1); + BOOST_TEST(cp2.second() == p2); + // second param construct: + boost::compressed_pair<T1,T2> cp3(p2); + cp3.first() = p1; + BOOST_TEST(cp3.second() == p2); + BOOST_TEST(cp3.first() == p1); + // both param construct: + boost::compressed_pair<T1,T2> cp4(p1, p2); + BOOST_TEST(cp4.first() == p1); + BOOST_TEST(cp4.second() == p2); + boost::compressed_pair<T1,T2> cp5(p3, p4); + BOOST_TEST(cp5.first() == p3); + BOOST_TEST(cp5.second() == p4); + // check const members: + const boost::compressed_pair<T1,T2>& cpr1 = cp4; + BOOST_TEST(cpr1.first() == p1); + BOOST_TEST(cpr1.second() == p2); + + // copy construct: + boost::compressed_pair<T1,T2> cp6(cp4); + BOOST_TEST(cp6.first() == p1); + BOOST_TEST(cp6.second() == p2); + // assignment: + cp1 = cp4; + BOOST_TEST(cp1.first() == p1); + BOOST_TEST(cp1.second() == p2); + cp1 = cp5; + BOOST_TEST(cp1.first() == p3); + BOOST_TEST(cp1.second() == p4); + // swap: + cp4.swap(cp5); + BOOST_TEST(cp4.first() == p3); + BOOST_TEST(cp4.second() == p4); + BOOST_TEST(cp5.first() == p1); + BOOST_TEST(cp5.second() == p2); + swap(cp4,cp5); + BOOST_TEST(cp4.first() == p1); + BOOST_TEST(cp4.second() == p2); + BOOST_TEST(cp5.first() == p3); + BOOST_TEST(cp5.second() == p4); +} + +// +// tests for case where one or both +// parameters are reference types: +// +template <class T1, class T2> +struct compressed_pair_reference_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits<first_type>::param_type first_param_type; + typedef typename call_traits<second_type>::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template <class T1, class T2> +void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) +{ +#ifndef __GNUC__ + // gcc 2.90 can't cope with function scope using + // declarations, and generates an internal compiler error... + using std::swap; +#endif + // both param construct: + boost::compressed_pair<T1,T2> cp4(p1, p2); + BOOST_TEST(cp4.first() == p1); + BOOST_TEST(cp4.second() == p2); + boost::compressed_pair<T1,T2> cp5(p3, p4); + BOOST_TEST(cp5.first() == p3); + BOOST_TEST(cp5.second() == p4); + // check const members: + const boost::compressed_pair<T1,T2>& cpr1 = cp4; + BOOST_TEST(cpr1.first() == p1); + BOOST_TEST(cpr1.second() == p2); + + // copy construct: + boost::compressed_pair<T1,T2> cp6(cp4); + BOOST_TEST(cp6.first() == p1); + BOOST_TEST(cp6.second() == p2); + // assignment: + // VC6 bug: + // When second() is an empty class, VC6 performs the + // assignment by doing a memcpy - even though the empty + // class is really a zero sized base class, the result + // is that the memory of first() gets trampled over. + // Similar arguments apply to the case that first() is + // an empty base class. + // Strangely the problem is dependent upon the compiler + // settings - some generate the problem others do not. + cp4.first() = p3; + cp4.second() = p4; + BOOST_TEST(cp4.first() == p3); + BOOST_TEST(cp4.second() == p4); +} +// +// supplimentary tests for case where first arg only is a reference type: +// +template <class T1, class T2> +struct compressed_pair_reference1_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits<first_type>::param_type first_param_type; + typedef typename call_traits<second_type>::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template <class T1, class T2> +void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // first param construct: + boost::compressed_pair<T1,T2> cp2(p1); + cp2.second() = p2; + BOOST_TEST(cp2.first() == p1); + BOOST_TEST(cp2.second() == p2); +#endif +} +// +// supplimentary tests for case where second arg only is a reference type: +// +template <class T1, class T2> +struct compressed_pair_reference2_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits<first_type>::param_type first_param_type; + typedef typename call_traits<second_type>::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template <class T1, class T2> +void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // second param construct: + boost::compressed_pair<T1,T2> cp3(p2); + cp3.first() = p1; + BOOST_TEST(cp3.second() == p2); + BOOST_TEST(cp3.first() == p1); +#endif +} + +// +// tests for where one or the other parameter is an array: +// +template <class T1, class T2> +struct compressed_pair_array1_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits<first_type>::param_type first_param_type; + typedef typename call_traits<second_type>::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template <class T1, class T2> +void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ + // default construct: + boost::compressed_pair<T1,T2> cp1; + // second param construct: + boost::compressed_pair<T1,T2> cp3(p2); + cp3.first()[0] = p1[0]; + BOOST_TEST(cp3.second() == p2); + BOOST_TEST(cp3.first()[0] == p1[0]); + // check const members: + const boost::compressed_pair<T1,T2>& cpr1 = cp3; + BOOST_TEST(cpr1.first()[0] == p1[0]); + BOOST_TEST(cpr1.second() == p2); + + BOOST_TEST(sizeof(T1) == sizeof(cp1.first())); +} + +template <class T1, class T2> +struct compressed_pair_array2_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits<first_type>::param_type first_param_type; + typedef typename call_traits<second_type>::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template <class T1, class T2> +void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ + // default construct: + boost::compressed_pair<T1,T2> cp1; + // first param construct: + boost::compressed_pair<T1,T2> cp2(p1); + cp2.second()[0] = p2[0]; + BOOST_TEST(cp2.first() == p1); + BOOST_TEST(cp2.second()[0] == p2[0]); + // check const members: + const boost::compressed_pair<T1,T2>& cpr1 = cp2; + BOOST_TEST(cpr1.first() == p1); + BOOST_TEST(cpr1.second()[0] == p2[0]); + + BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); +} + +template <class T1, class T2> +struct compressed_pair_array_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits<first_type>::param_type first_param_type; + typedef typename call_traits<second_type>::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template <class T1, class T2> +void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ + // default construct: + boost::compressed_pair<T1,T2> cp1; + cp1.first()[0] = p1[0]; + cp1.second()[0] = p2[0]; + BOOST_TEST(cp1.first()[0] == p1[0]); + BOOST_TEST(cp1.second()[0] == p2[0]); + // check const members: + const boost::compressed_pair<T1,T2>& cpr1 = cp1; + BOOST_TEST(cpr1.first()[0] == p1[0]); + BOOST_TEST(cpr1.second()[0] == p2[0]); + + BOOST_TEST(sizeof(T1) == sizeof(cp1.first())); + BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); +} + +int main() +{ + // declare some variables to pass to the tester: + non_empty1 ne1(2); + non_empty1 ne2(3); + non_empty2 ne3(4); + non_empty2 ne4(5); + empty_POD_UDT e1; + empty_UDT e2; + + // T1 != T2, both non-empty + compressed_pair_tester<non_empty1,non_empty2>::test(ne1, ne3, ne2, ne4); + // T1 != T2, T2 empty + compressed_pair_tester<non_empty1,empty_POD_UDT>::test(ne1, e1, ne2, e1); + // T1 != T2, T1 empty + compressed_pair_tester<empty_POD_UDT,non_empty2>::test(e1, ne3, e1, ne4); + // T1 != T2, both empty + compressed_pair_tester<empty_POD_UDT,empty_UDT>::test(e1, e2, e1, e2); + // T1 == T2, both non-empty + compressed_pair_tester<non_empty1,non_empty1>::test(ne1, ne1, ne2, ne2); + // T1 == T2, both empty + compressed_pair_tester<empty_UDT,empty_UDT>::test(e2, e2, e2, e2); + + + // test references: + + // T1 != T2, both non-empty + compressed_pair_reference_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4); + compressed_pair_reference_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4); + compressed_pair_reference1_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4); + compressed_pair_reference2_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4); + // T1 != T2, T2 empty + compressed_pair_reference_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1); + compressed_pair_reference1_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1); + // T1 != T2, T1 empty + compressed_pair_reference_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4); + compressed_pair_reference2_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4); + // T1 == T2, both non-empty + compressed_pair_reference_tester<non_empty1&,non_empty1&>::test(ne1, ne1, ne2, ne2); + + // tests arrays: + non_empty1 nea1[2]; + non_empty1 nea2[2]; + non_empty2 nea3[2]; + non_empty2 nea4[2]; + nea1[0] = non_empty1(5); + nea2[0] = non_empty1(6); + nea3[0] = non_empty2(7); + nea4[0] = non_empty2(8); + + // T1 != T2, both non-empty + compressed_pair_array1_tester<non_empty1[2],non_empty2>::test(nea1, ne3, nea2, ne4); + compressed_pair_array2_tester<non_empty1,non_empty2[2]>::test(ne1, nea3, ne2, nea4); + compressed_pair_array_tester<non_empty1[2],non_empty2[2]>::test(nea1, nea3, nea2, nea4); + // T1 != T2, T2 empty + compressed_pair_array1_tester<non_empty1[2],empty_POD_UDT>::test(nea1, e1, nea2, e1); + // T1 != T2, T1 empty + compressed_pair_array2_tester<empty_POD_UDT,non_empty2[2]>::test(e1, nea3, e1, nea4); + // T1 == T2, both non-empty + compressed_pair_array_tester<non_empty1[2],non_empty1[2]>::test(nea1, nea1, nea2, nea2); + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/initialized_test.cpp b/src/boost/libs/utility/test/initialized_test.cpp new file mode 100644 index 000000000..0b8852f12 --- /dev/null +++ b/src/boost/libs/utility/test/initialized_test.cpp @@ -0,0 +1,116 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for boost::initialized<T>. +// +// 2 May 2010 (Created) Niels Dekker + +#include <boost/utility/value_init.hpp> +#include <boost/core/lightweight_test.hpp> + +#include <string> + +namespace +{ + // Typical use case for boost::initialized<T>: A generic class that + // holds a value of type T, which must be initialized by either + // value-initialization or direct-initialization. + template <class T> class key_value_pair + { + std::string m_key; + boost::initialized<T> m_value; + public: + + // Value-initializes the object held by m_value. + key_value_pair() { } + + // Value-initializes the object held by m_value. + explicit key_value_pair(const std::string& key) + : + m_key(key) + { + } + + // Direct-initializes the object held by m_value. + key_value_pair(const std::string& key, const T& value) + : + m_key(key), m_value(value) + { + } + + const T& get_value() const + { + return m_value; + } + }; + + + // Tells whether the argument is value-initialized. + bool is_value_initialized(const int& arg) + { + return arg == 0; + } + + + // Tells whether the argument is value-initialized. + bool is_value_initialized(const std::string& arg) + { + return arg.empty(); + } + + struct foo + { + int data; + }; + + bool operator==(const foo& lhs, const foo& rhs) + { + return lhs.data == rhs.data; + } + + + // Tells whether the argument is value-initialized. + bool is_value_initialized(const foo& arg) + { + return arg.data == 0; + } + + + template <class T> + void test_key_value_pair(const T& magic_value) + { + // The value component of a default key_value_pair must be value-initialized. + key_value_pair<T> default_key_value_pair; + BOOST_TEST( is_value_initialized(default_key_value_pair.get_value() ) ); + + // The value component of a key_value_pair that only has its key explicitly specified + // must also be value-initialized. + BOOST_TEST( is_value_initialized(key_value_pair<T>("key").get_value()) ); + + // However, the value component of the following key_value_pair must be + // "magic_value", as it must be direct-initialized. + BOOST_TEST( key_value_pair<T>("key", magic_value).get_value() == magic_value ); + } +} + + +// Tests boost::initialize for a fundamental type, a type with a +// user-defined constructor, and a user-defined type without +// a user-defined constructor. +int main() +{ + + const int magic_number = 42; + test_key_value_pair(magic_number); + + const std::string magic_string = "magic value"; + test_key_value_pair(magic_string); + + const foo magic_foo = { 42 }; + test_key_value_pair(magic_foo); + + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/initialized_test_fail1.cpp b/src/boost/libs/utility/test/initialized_test_fail1.cpp new file mode 100644 index 000000000..ffeecab5b --- /dev/null +++ b/src/boost/libs/utility/test/initialized_test_fail1.cpp @@ -0,0 +1,33 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for boost::initialized<T>. Must fail to compile. +// +// Initial: 2 May 2010 + +#include <boost/utility/value_init.hpp> + +namespace +{ + void direct_initialize_from_int() + { + // Okay: initialized<T> supports direct-initialization from T. + boost::initialized<int> direct_initialized_int(1); + } + + void copy_initialize_from_int() + { + // The following line should not compile, because initialized<T> + // was not intended to supports copy-initialization from T. + boost::initialized<int> copy_initialized_int = 1; + } +} + +int main() +{ + // This should fail to compile, so there is no need to call any function. + return 0; +} diff --git a/src/boost/libs/utility/test/initialized_test_fail2.cpp b/src/boost/libs/utility/test/initialized_test_fail2.cpp new file mode 100644 index 000000000..f3fbf391e --- /dev/null +++ b/src/boost/libs/utility/test/initialized_test_fail2.cpp @@ -0,0 +1,37 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for boost::initialized<T>. Must fail to compile. +// +// Initial: 2 May 2010 + +#include <boost/utility/value_init.hpp> + +namespace +{ + void from_value_initialized_to_initialized() + { + boost::value_initialized<int> value_initialized_int; + + // Okay: initialized<T> can be initialized by value_initialized<T>. + boost::initialized<int> initialized_int(value_initialized_int); + } + + void from_initialized_to_value_initialized() + { + boost::initialized<int> initialized_int(13); + + // The following line should not compile, because initialized<T> + // should not be convertible to value_initialized<T>. + boost::value_initialized<int> value_initialized_int(initialized_int); + } +} + +int main() +{ + // This should fail to compile, so there is no need to call any function. + return 0; +} diff --git a/src/boost/libs/utility/test/iterators_test.cpp b/src/boost/libs/utility/test/iterators_test.cpp new file mode 100644 index 000000000..8f2d04d05 --- /dev/null +++ b/src/boost/libs/utility/test/iterators_test.cpp @@ -0,0 +1,322 @@ +// Demonstrate and test boost/operators.hpp on std::iterators --------------// + +// (C) Copyright Jeremy Siek 1999. +// 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) + +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 29 May 01 Factored implementation, added comparison tests, use Test Tools +// library (Daryle Walker) +// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) + +#include <boost/core/lightweight_test.hpp> + +#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT +#include <boost/operators.hpp> // for boost::random_access_iterator_helper + +#include <cstddef> // for std::ptrdiff_t, std::size_t +#include <cstring> // for std::strcmp +#include <iostream> // for std::cout (std::endl, ends, and flush indirectly) +#include <string> // for std::string +#include <sstream> // for std::stringstream + +# ifdef BOOST_NO_STDC_NAMESPACE + namespace std { using ::strcmp; } +# endif + + +// Iterator test class +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) : _i(i) { } + test_iter(const self& x) : _i(x._i) { } + self& operator=(const self& x) { _i = x._i; return *this; } + Reference operator*() const { return *_i; } + self& operator++() { ++_i; return *this; } + self& operator--() { --_i; return *this; } + self& operator+=(Distance n) { _i += n; return *this; } + self& operator-=(Distance n) { _i -= n; return *this; } + bool operator==(const self& x) const { return _i == x._i; } + bool operator<(const self& x) const { return _i < x._i; } + friend Distance operator-(const self& x, const self& y) { + return x._i - y._i; + } +protected: + P _i; +}; + +// Iterator operator testing classes +class test_opr_base +{ +protected: + // Test data and types + BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u ); + + typedef std::string fruit_array_type[ fruit_length ]; + + static fruit_array_type fruit; + +}; // test_opr_base + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +const std::size_t test_opr_base::fruit_length; +#endif + +template <typename T, typename R = T&, typename P = T*> +class test_opr + : public test_opr_base +{ + typedef test_opr<T, R, P> self_type; + +public: + // Types + typedef T value_type; + typedef R reference; + typedef P pointer; + + typedef test_iter<T, R, P> iter_type; + + // Test controller + static void master_test( char const name[] ); + +private: + // Test data + static iter_type const fruit_begin; + static iter_type const fruit_end; + + // Test parts + static void post_increment_test(); + static void post_decrement_test(); + static void indirect_referral_test(); + static void offset_addition_test(); + static void reverse_offset_addition_test(); + static void offset_subtraction_test(); + static void comparison_test(); + static void indexing_test(); + +}; // test_opr + + +// Class-static data definitions +test_opr_base::fruit_array_type + test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" }; + +template <typename T, typename R, typename P> + typename test_opr<T, R, P>::iter_type const + test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit ); + +template <typename T, typename R, typename P> +typename test_opr<T, R, P>::iter_type const + test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length ); + + +// Main testing function +int +main() +{ + using std::string; + + typedef test_opr<string, string &, string *> test1_type; + typedef test_opr<string, string const &, string const *> test2_type; + + test1_type::master_test( "non-const string" ); + test2_type::master_test( "const string" ); + + return boost::report_errors(); +} + +// Tests for all of the operators added by random_access_iterator_helper +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::master_test +( + char const name[] +) +{ + std::cout << "Doing test run for " << name << '.' << std::endl; + + post_increment_test(); + post_decrement_test(); + indirect_referral_test(); + offset_addition_test(); + reverse_offset_addition_test(); + offset_subtraction_test(); + comparison_test(); + indexing_test(); +} + +// Test post-increment +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::post_increment_test +( +) +{ + std::cout << "\tDoing post-increment test." << std::endl; + + std::stringstream oss; + for ( iter_type i = fruit_begin ; i != fruit_end ; ) + { + oss << *i++ << ' '; + } + + BOOST_TEST( oss.str() == "apple orange pear peach grape plum "); +} + +// Test post-decrement +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::post_decrement_test +( +) +{ + std::cout << "\tDoing post-decrement test." << std::endl; + + std::stringstream oss; + for ( iter_type i = fruit_end ; i != fruit_begin ; ) + { + i--; + oss << *i << ' '; + } + + BOOST_TEST( oss.str() == "plum grape peach pear orange apple "); +} + +// Test indirect structure referral +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::indirect_referral_test +( +) +{ + std::cout << "\tDoing indirect reference test." << std::endl; + + std::stringstream oss; + for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) + { + oss << i->size() << ' '; + } + + BOOST_TEST( oss.str() == "5 6 4 5 5 4 "); +} + +// Test offset addition +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::offset_addition_test +( +) +{ + std::cout << "\tDoing offset addition test." << std::endl; + + std::ptrdiff_t const two = 2; + std::stringstream oss; + for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two ) + { + oss << *i << ' '; + } + + BOOST_TEST( oss.str() == "apple pear grape "); +} + +// Test offset addition, in reverse order +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::reverse_offset_addition_test +( +) +{ + std::cout << "\tDoing reverse offset addition test." << std::endl; + + std::ptrdiff_t const two = 2; + std::stringstream oss; + for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i ) + { + oss << *i << ' '; + } + + BOOST_TEST( oss.str() == "apple pear grape "); +} + +// Test offset subtraction +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::offset_subtraction_test +( +) +{ + std::cout << "\tDoing offset subtraction test." << std::endl; + + std::ptrdiff_t const two = 2; + std::stringstream oss; + for ( iter_type i = fruit_end ; fruit_begin < i ; ) + { + i = i - two; + if ( (fruit_begin < i) || (fruit_begin == i) ) + { + oss << *i << ' '; + } + } + + BOOST_TEST( oss.str() == "grape pear apple "); +} + +// Test comparisons +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::comparison_test +( +) +{ + using std::cout; + using std::ptrdiff_t; + + cout << "\tDoing comparison tests.\n\t\tPass:"; + + for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) + { + ptrdiff_t const i_offset = i - fruit_begin; + + cout << ' ' << *i << std::flush; + for ( iter_type j = fruit_begin ; j != fruit_end ; ++j ) + { + ptrdiff_t const j_offset = j - fruit_begin; + + BOOST_TEST( (i != j) == (i_offset != j_offset) ); + BOOST_TEST( (i > j) == (i_offset > j_offset) ); + BOOST_TEST( (i <= j) == (i_offset <= j_offset) ); + BOOST_TEST( (i >= j) == (i_offset >= j_offset) ); + } + } + cout << std::endl; +} + +// Test indexing +template <typename T, typename R, typename P> +void +test_opr<T, R, P>::indexing_test +( +) +{ + std::cout << "\tDoing indexing test." << std::endl; + + std::stringstream oss; + for ( std::size_t k = 0u ; k < fruit_length ; ++k ) + { + oss << fruit_begin[ k ] << ' '; + } + + BOOST_TEST( oss.str() == "apple orange pear peach grape plum "); +} diff --git a/src/boost/libs/utility/test/operators_test.cpp b/src/boost/libs/utility/test/operators_test.cpp new file mode 100644 index 000000000..6cf7a76cf --- /dev/null +++ b/src/boost/libs/utility/test/operators_test.cpp @@ -0,0 +1,936 @@ +// Demonstrate and test boost/operators.hpp -------------------------------// + +// Copyright Beman Dawes 1999. 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) + +// See http://www.boost.org/libs/utility for documentation. + +// Revision History +// 03 Apr 08 Added convertible_to_bool (Daniel Frey) +// 01 Oct 01 Added tests for "left" operators +// and new grouped operators. (Helmut Zeisel) +// 20 May 01 Output progress messages. Added tests for new operator +// templates. Updated random number generator. Changed tests to +// use Boost Test Tools library. (Daryle Walker) +// 04 Jun 00 Added regression test for a bug I found (David Abrahams) +// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy) +// ?? ??? 00 Major update to randomly test all one- and two- argument forms by +// wrapping integral types and comparing the results of operations +// to the results for the raw types (David Abrahams) +// 12 Dec 99 Minor update, output confirmation message. +// 15 Nov 99 Initial version + +#include <boost/config.hpp> // for BOOST_MSVC +#include <boost/operators.hpp> // for the tested items +#include <boost/utility/detail/minstd_rand.hpp> // for boost::detail::minstd_rand +#include <boost/core/lightweight_test.hpp> + +#include <iostream> // for std::cout (std::endl indirectly) + + +namespace +{ + // avoiding a template version of true_value so as to not confuse VC++ + int true_value(int x) { return x; } + long true_value(long x) { return x; } + signed char true_value(signed char x) { return x; } + unsigned int true_value(unsigned int x) { return x; } + unsigned long true_value(unsigned long x) { return x; } + unsigned char true_value(unsigned char x) { return x; } + + // verify the minimum requirements for some operators + class convertible_to_bool + { + private: + bool _value; + + typedef bool convertible_to_bool::*unspecified_bool_type; + + void operator!() const; + + public: + convertible_to_bool( const bool value ) : _value( value ) {} + + operator unspecified_bool_type() const + { return _value ? &convertible_to_bool::_value : 0; } + }; + + // The use of operators<> here tended to obscure + // interactions with certain compiler bugs + template <class T> + class Wrapped1 + : boost::operators<Wrapped1<T> > + , boost::shiftable<Wrapped1<T> > + { + public: + explicit Wrapped1( T v = T() ) : _value(v) {} + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped1& x) const + { return _value < x._value; } + convertible_to_bool operator==(const Wrapped1& x) const + { return _value == x._value; } + + Wrapped1& operator+=(const Wrapped1& x) + { _value += x._value; return *this; } + Wrapped1& operator-=(const Wrapped1& x) + { _value -= x._value; return *this; } + Wrapped1& operator*=(const Wrapped1& x) + { _value *= x._value; return *this; } + Wrapped1& operator/=(const Wrapped1& x) + { _value /= x._value; return *this; } + Wrapped1& operator%=(const Wrapped1& x) + { _value %= x._value; return *this; } + Wrapped1& operator|=(const Wrapped1& x) + { _value |= x._value; return *this; } + Wrapped1& operator&=(const Wrapped1& x) + { _value &= x._value; return *this; } + Wrapped1& operator^=(const Wrapped1& x) + { _value ^= x._value; return *this; } + Wrapped1& operator<<=(const Wrapped1& x) + { _value <<= x._value; return *this; } + Wrapped1& operator>>=(const Wrapped1& x) + { _value >>= x._value; return *this; } + Wrapped1& operator++() { ++_value; return *this; } + Wrapped1& operator--() { --_value; return *this; } + + private: + T _value; + }; + template <class T> + T true_value(Wrapped1<T> x) { return x.value(); } + + template <class T, class U> + class Wrapped2 + : boost::operators<Wrapped2<T, U> > + , boost::operators2<Wrapped2<T, U>, U> + , boost::shiftable1<Wrapped2<T, U> + , boost::shiftable2<Wrapped2<T, U>, U > > + { + public: + explicit Wrapped2( T v = T() ) : _value(v) {} + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped2& x) const + { return _value < x._value; } + convertible_to_bool operator==(const Wrapped2& x) const + { return _value == x._value; } + + Wrapped2& operator+=(const Wrapped2& x) + { _value += x._value; return *this; } + Wrapped2& operator-=(const Wrapped2& x) + { _value -= x._value; return *this; } + Wrapped2& operator*=(const Wrapped2& x) + { _value *= x._value; return *this; } + Wrapped2& operator/=(const Wrapped2& x) + { _value /= x._value; return *this; } + Wrapped2& operator%=(const Wrapped2& x) + { _value %= x._value; return *this; } + Wrapped2& operator|=(const Wrapped2& x) + { _value |= x._value; return *this; } + Wrapped2& operator&=(const Wrapped2& x) + { _value &= x._value; return *this; } + Wrapped2& operator^=(const Wrapped2& x) + { _value ^= x._value; return *this; } + Wrapped2& operator<<=(const Wrapped2& x) + { _value <<= x._value; return *this; } + Wrapped2& operator>>=(const Wrapped2& x) + { _value >>= x._value; return *this; } + Wrapped2& operator++() { ++_value; return *this; } + Wrapped2& operator--() { --_value; return *this; } + + convertible_to_bool operator<(U u) const + { return _value < u; } + convertible_to_bool operator>(U u) const + { return _value > u; } + convertible_to_bool operator==(U u) const + { return _value == u; } + + Wrapped2& operator+=(U u) { _value += u; return *this; } + Wrapped2& operator-=(U u) { _value -= u; return *this; } + Wrapped2& operator*=(U u) { _value *= u; return *this; } + Wrapped2& operator/=(U u) { _value /= u; return *this; } + Wrapped2& operator%=(U u) { _value %= u; return *this; } + Wrapped2& operator|=(U u) { _value |= u; return *this; } + Wrapped2& operator&=(U u) { _value &= u; return *this; } + Wrapped2& operator^=(U u) { _value ^= u; return *this; } + Wrapped2& operator<<=(U u) { _value <<= u; return *this; } + Wrapped2& operator>>=(U u) { _value >>= u; return *this; } + + private: + T _value; + }; + template <class T, class U> + T true_value(Wrapped2<T,U> x) { return x.value(); } + + template <class T> + class Wrapped3 + : boost::equivalent<Wrapped3<T> > + , boost::partially_ordered<Wrapped3<T> > + , boost::equality_comparable<Wrapped3<T> > + { + public: + explicit Wrapped3( T v = T() ) : _value(v) {} + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped3& x) const + { return _value < x._value; } + + private: + T _value; + }; + template <class T> + T true_value(Wrapped3<T> x) { return x.value(); } + + template <class T, class U> + class Wrapped4 + : boost::equality_comparable1<Wrapped4<T, U> + , boost::equivalent1<Wrapped4<T, U> + , boost::partially_ordered1<Wrapped4<T, U> > > > + , boost::partially_ordered2<Wrapped4<T, U>, U + , boost::equivalent2<Wrapped4<T, U>, U + , boost::equality_comparable2<Wrapped4<T, U>, U> > > + { + public: + explicit Wrapped4( T v = T() ) : _value(v) {} + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped4& x) const + { return _value < x._value; } + + convertible_to_bool operator<(U u) const + { return _value < u; } + convertible_to_bool operator>(U u) const + { return _value > u; } + + private: + T _value; + }; + template <class T, class U> + T true_value(Wrapped4<T,U> x) { return x.value(); } + + // U must be convertible to T + template <class T, class U> + class Wrapped5 + : boost::ordered_field_operators2<Wrapped5<T, U>, U> + , boost::ordered_field_operators1<Wrapped5<T, U> > + { + public: + explicit Wrapped5( T v = T() ) : _value(v) {} + + // Conversion from U to Wrapped5<T,U> + Wrapped5(U u) : _value(u) {} + + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped5& x) const + { return _value < x._value; } + convertible_to_bool operator<(U u) const + { return _value < u; } + convertible_to_bool operator>(U u) const + { return _value > u; } + convertible_to_bool operator==(const Wrapped5& u) const + { return _value == u._value; } + convertible_to_bool operator==(U u) const + { return _value == u; } + + Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;} + Wrapped5& operator/=(U u) { _value /= u; return *this;} + Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;} + Wrapped5& operator*=(U u) { _value *= u; return *this;} + Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;} + Wrapped5& operator-=(U u) { _value -= u; return *this;} + Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;} + Wrapped5& operator+=(U u) { _value += u; return *this;} + + private: + T _value; + }; + template <class T, class U> + T true_value(Wrapped5<T,U> x) { return x.value(); } + + // U must be convertible to T + template <class T, class U> + class Wrapped6 + : boost::ordered_euclidean_ring_operators2<Wrapped6<T, U>, U> + , boost::ordered_euclidean_ring_operators1<Wrapped6<T, U> > + { + public: + explicit Wrapped6( T v = T() ) : _value(v) {} + + // Conversion from U to Wrapped6<T,U> + Wrapped6(U u) : _value(u) {} + + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped6& x) const + { return _value < x._value; } + convertible_to_bool operator<(U u) const + { return _value < u; } + convertible_to_bool operator>(U u) const + { return _value > u; } + convertible_to_bool operator==(const Wrapped6& u) const + { return _value == u._value; } + convertible_to_bool operator==(U u) const + { return _value == u; } + + Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;} + Wrapped6& operator%=(U u) { _value %= u; return *this;} + Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;} + Wrapped6& operator/=(U u) { _value /= u; return *this;} + Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;} + Wrapped6& operator*=(U u) { _value *= u; return *this;} + Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;} + Wrapped6& operator-=(U u) { _value -= u; return *this;} + Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;} + Wrapped6& operator+=(U u) { _value += u; return *this;} + + private: + T _value; + }; + template <class T, class U> + T true_value(Wrapped6<T,U> x) { return x.value(); } + + // MyInt uses only the single template-argument form of all_operators<> + typedef Wrapped1<int> MyInt; + + typedef Wrapped2<long, long> MyLong; + + typedef Wrapped3<signed char> MyChar; + + typedef Wrapped4<short, short> MyShort; + + typedef Wrapped5<double, int> MyDoubleInt; + + typedef Wrapped6<long, int> MyLongInt; + + template <class X1, class Y1, class X2, class Y2> + void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + BOOST_TEST( true_value(y1) == true_value(y2) ); + BOOST_TEST( true_value(x1) == true_value(x2) ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + BOOST_TEST( static_cast<bool>(x1 < y1) == static_cast<bool>(x2 < y2) ); + BOOST_TEST( static_cast<bool>(x1 <= y1) == static_cast<bool>(x2 <= y2) ); + BOOST_TEST( static_cast<bool>(x1 >= y1) == static_cast<bool>(x2 >= y2) ); + BOOST_TEST( static_cast<bool>(x1 > y1) == static_cast<bool>(x2 > y2) ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_less_than_comparable_aux( x1, y1, x2, y2 ); + test_less_than_comparable_aux( y1, x1, y2, x2 ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + BOOST_TEST( static_cast<bool>(x1 == y1) == static_cast<bool>(x2 == y2) ); + BOOST_TEST( static_cast<bool>(x1 != y1) == static_cast<bool>(x2 != y2) ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_equality_comparable_aux( x1, y1, x2, y2 ); + test_equality_comparable_aux( y1, x1, y2, x2 ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + BOOST_TEST( (x1 * y1).value() == (x2 * y2) ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_multipliable_aux( x1, y1, x2, y2 ); + test_multipliable_aux( y1, x1, y2, x2 ); + } + + template <class A, class B> + void test_value_equality(A a, B b) + { + BOOST_TEST(a.value() == b); + } + +#define TEST_OP_R(op) test_value_equality(x1 op y1, x2 op y2) +#define TEST_OP_L(op) test_value_equality(y1 op x1, y2 op x2) + + template <class X1, class Y1, class X2, class Y2> + void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + TEST_OP_R(+); + } + + template <class X1, class Y1, class X2, class Y2> + void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_addable_aux( x1, y1, x2, y2 ); + test_addable_aux( y1, x1, y2, x2 ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + TEST_OP_R(-); + } + + template <class X1, class Y1, class X2, class Y2> + void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + TEST_OP_L(-); + } + + template <class X1, class Y1, class X2, class Y2> + void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( y2 != 0 ) + TEST_OP_R(/); + } + + template <class X1, class Y1, class X2, class Y2> + void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( x2 != 0 ) + TEST_OP_L(/); + } + + template <class X1, class Y1, class X2, class Y2> + void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( y2 != 0 ) + TEST_OP_R(%); + } + + template <class X1, class Y1, class X2, class Y2> + void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( x2 != 0 ) + TEST_OP_L(%); + } + + template <class X1, class Y1, class X2, class Y2> + void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + TEST_OP_R(^); + } + + template <class X1, class Y1, class X2, class Y2> + void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_xorable_aux( x1, y1, x2, y2 ); + test_xorable_aux( y1, x1, y2, x2 ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + TEST_OP_R(&); + } + + template <class X1, class Y1, class X2, class Y2> + void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_andable_aux( x1, y1, x2, y2 ); + test_andable_aux( y1, x1, y2, x2 ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + TEST_OP_R(|); + } + + template <class X1, class Y1, class X2, class Y2> + void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_orable_aux( x1, y1, x2, y2 ); + test_orable_aux( y1, x1, y2, x2 ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + TEST_OP_R(<<); + } + + template <class X1, class Y1, class X2, class Y2> + void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + TEST_OP_R(>>); + } + + template <class X1, class X2> + void test_incrementable(X1 x1, X2 x2) + { + sanity_check( x1, x1, x2, x2 ); + BOOST_TEST( (x1++).value() == x2++ ); + BOOST_TEST( x1.value() == x2 ); + } + + template <class X1, class X2> + void test_decrementable(X1 x1, X2 x2) + { + sanity_check( x1, x1, x2, x2 ); + BOOST_TEST( (x1--).value() == x2-- ); + BOOST_TEST( x1.value() == x2 ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + test_less_than_comparable( x1, y1, x2, y2 ); + test_equality_comparable( x1, y1, x2, y2 ); + test_multipliable( x1, y1, x2, y2 ); + test_addable( x1, y1, x2, y2 ); + test_subtractable( x1, y1, x2, y2 ); + test_dividable( x1, y1, x2, y2 ); + test_modable( x1, y1, x2, y2 ); + test_xorable( x1, y1, x2, y2 ); + test_andable( x1, y1, x2, y2 ); + test_orable( x1, y1, x2, y2 ); + test_left_shiftable( x1, y1, x2, y2 ); + test_right_shiftable( x1, y1, x2, y2 ); + test_incrementable( x1, x2 ); + test_decrementable( x1, x2 ); + } + + template <class X1, class Y1, class X2, class Y2> + void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + test_subtractable_left( x1, y1, x2, y2 ); + test_dividable_left( x1, y1, x2, y2 ); + test_modable_left( x1, y1, x2, y2 ); + } + + template <class Big, class Small> + struct tester + { + void operator()(boost::detail::minstd_rand& randomizer) const + { + Big b1 = Big( randomizer() ); + Big b2 = Big( randomizer() ); + Small s = Small( randomizer() ); + + test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 ); + test_all( Wrapped2<Big, Small>(b1), s, b1, s ); + } + }; + + template <class Big, class Small> + struct tester_left + { + void operator()(boost::detail::minstd_rand& randomizer) const + { + Big b1 = Big( randomizer() ); + Small s = Small( randomizer() ); + + test_left( Wrapped6<Big, Small>(b1), s, b1, s ); + } + }; + + // added as a regression test. We had a bug which this uncovered. + struct Point + : boost::addable<Point + , boost::subtractable<Point> > + { + Point( int h, int v ) : h(h), v(v) {} + Point() :h(0), v(0) {} + const Point& operator+=( const Point& rhs ) + { h += rhs.h; v += rhs.v; return *this; } + const Point& operator-=( const Point& rhs ) + { h -= rhs.h; v -= rhs.v; return *this; } + + int h; + int v; + }; + +} // unnamed namespace + + +// workaround for MSVC bug; for some reasons the compiler doesn't instantiate +// inherited operator templates at the moment it must, so the following +// explicit instantiations force it to do that. + +#if defined(BOOST_MSVC) && (_MSC_VER < 1300) +template Wrapped1<int>; +template Wrapped1<long>; +template Wrapped1<unsigned int>; +template Wrapped1<unsigned long>; + +template Wrapped2<int, int>; +template Wrapped2<int, signed char>; +template Wrapped2<long, signed char>; +template Wrapped2<long, int>; +template Wrapped2<long, long>; +template Wrapped2<unsigned int, unsigned int>; +template Wrapped2<unsigned int, unsigned char>; +template Wrapped2<unsigned long, unsigned int>; +template Wrapped2<unsigned long, unsigned char>; +template Wrapped2<unsigned long, unsigned long>; + +template Wrapped6<long, int>; +template Wrapped6<long, signed char>; +template Wrapped6<int, signed char>; +template Wrapped6<unsigned long, unsigned int>; +template Wrapped6<unsigned long, unsigned char>; +template Wrapped6<unsigned int, unsigned char>; +#endif + +#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) ) + +int +main() +{ + using std::cout; + using std::endl; + + // Regression test. + Point x; + x = x + Point(3, 4); + x = x - Point(3, 4); + + cout << "Created point, and operated on it." << endl; + + for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman) + { + boost::detail::minstd_rand r; + tester<long, int>()(r); + tester<long, signed char>()(r); + tester<long, long>()(r); + tester<int, int>()(r); + tester<int, signed char>()(r); + + tester<unsigned long, unsigned int>()(r); + tester<unsigned long, unsigned char>()(r); + tester<unsigned long, unsigned long>()(r); + tester<unsigned int, unsigned int>()(r); + tester<unsigned int, unsigned char>()(r); + + tester_left<long, int>()(r); + tester_left<long, signed char>()(r); + tester_left<int, signed char>()(r); + + tester_left<unsigned long, unsigned int>()(r); + tester_left<unsigned long, unsigned char>()(r); + tester_left<unsigned int, unsigned char>()(r); + } + + cout << "Did random tester loop." << endl; + + MyInt i1(1); + MyInt i2(2); + MyInt i; + + BOOST_TEST( i1.value() == 1 ); + BOOST_TEST( i2.value() == 2 ); + BOOST_TEST( i.value() == 0 ); + + cout << "Created MyInt objects.\n"; + + PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) ); + + BOOST_TEST( static_cast<bool>(i2 == i) ); + BOOST_TEST( static_cast<bool>(i1 != i2) ); + BOOST_TEST( static_cast<bool>(i1 < i2) ); + BOOST_TEST( static_cast<bool>(i1 <= i2) ); + BOOST_TEST( static_cast<bool>(i <= i2) ); + BOOST_TEST( static_cast<bool>(i2 > i1) ); + BOOST_TEST( static_cast<bool>(i2 >= i1) ); + BOOST_TEST( static_cast<bool>(i2 >= i) ); + + PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) ); + PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) ); + PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) ); + PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) ); + PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) ); + PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) ); + PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) ); + PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) ); + PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) ); + PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) ); + PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) ); + PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) ); + + PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) ); + PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) ); + + cout << "Performed tests on MyInt objects.\n"; + + MyLong j1(1); + MyLong j2(2); + MyLong j; + + BOOST_TEST( j1.value() == 1 ); + BOOST_TEST( j2.value() == 2 ); + BOOST_TEST( j.value() == 0 ); + + cout << "Created MyLong objects.\n"; + + PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) ); + + BOOST_TEST( static_cast<bool>(j2 == j) ); + BOOST_TEST( static_cast<bool>(2 == j) ); + BOOST_TEST( static_cast<bool>(j2 == 2) ); + BOOST_TEST( static_cast<bool>(j == j2) ); + BOOST_TEST( static_cast<bool>(j1 != j2) ); + BOOST_TEST( static_cast<bool>(j1 != 2) ); + BOOST_TEST( static_cast<bool>(1 != j2) ); + BOOST_TEST( static_cast<bool>(j1 < j2) ); + BOOST_TEST( static_cast<bool>(1 < j2) ); + BOOST_TEST( static_cast<bool>(j1 < 2) ); + BOOST_TEST( static_cast<bool>(j1 <= j2) ); + BOOST_TEST( static_cast<bool>(1 <= j2) ); + BOOST_TEST( static_cast<bool>(j1 <= j) ); + BOOST_TEST( static_cast<bool>(j <= j2) ); + BOOST_TEST( static_cast<bool>(2 <= j2) ); + BOOST_TEST( static_cast<bool>(j <= 2) ); + BOOST_TEST( static_cast<bool>(j2 > j1) ); + BOOST_TEST( static_cast<bool>(2 > j1) ); + BOOST_TEST( static_cast<bool>(j2 > 1) ); + BOOST_TEST( static_cast<bool>(j2 >= j1) ); + BOOST_TEST( static_cast<bool>(2 >= j1) ); + BOOST_TEST( static_cast<bool>(j2 >= 1) ); + BOOST_TEST( static_cast<bool>(j2 >= j) ); + BOOST_TEST( static_cast<bool>(2 >= j) ); + BOOST_TEST( static_cast<bool>(j2 >= 2) ); + + BOOST_TEST( static_cast<bool>((j1 + 2) == 3) ); + BOOST_TEST( static_cast<bool>((1 + j2) == 3) ); + PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) ); + + BOOST_TEST( static_cast<bool>((j + 2) == 5) ); + BOOST_TEST( static_cast<bool>((3 + j2) == 5) ); + PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) ); + + BOOST_TEST( static_cast<bool>((j - 1) == 4) ); + PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) ); + + BOOST_TEST( static_cast<bool>((j * 2) == 8) ); + BOOST_TEST( static_cast<bool>((4 * j2) == 8) ); + PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) ); + + BOOST_TEST( static_cast<bool>((j / 2) == 4) ); + PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) ); + + BOOST_TEST( static_cast<bool>((j % 3) == 1) ); + PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) ); + + PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) ); + + BOOST_TEST( static_cast<bool>((1 | j2 | j) == 7) ); + BOOST_TEST( static_cast<bool>((j1 | 2 | j) == 7) ); + BOOST_TEST( static_cast<bool>((j1 | j2 | 4) == 7) ); + PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) ); + + BOOST_TEST( static_cast<bool>((7 & j2) == 2) ); + BOOST_TEST( static_cast<bool>((j & 2) == 2) ); + PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) ); + + PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) ); + + BOOST_TEST( static_cast<bool>((3 ^ j1) == 2) ); + BOOST_TEST( static_cast<bool>((j ^ 1) == 2) ); + PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) ); + + PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) ); + + BOOST_TEST( static_cast<bool>((j1 << 2) == 4) ); + BOOST_TEST( static_cast<bool>((j2 << 1) == 4) ); + PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) ); + + BOOST_TEST( static_cast<bool>((j >> 2) == 1) ); + BOOST_TEST( static_cast<bool>((j2 >> 1) == 1) ); + PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) ); + + cout << "Performed tests on MyLong objects.\n"; + + MyChar k1(1); + MyChar k2(2); + MyChar k; + + BOOST_TEST( k1.value() == 1 ); + BOOST_TEST( k2.value() == 2 ); + BOOST_TEST( k.value() == 0 ); + + cout << "Created MyChar objects.\n"; + + PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) ); + + BOOST_TEST( static_cast<bool>(k2 == k) ); + BOOST_TEST( static_cast<bool>(k1 != k2) ); + BOOST_TEST( static_cast<bool>(k1 < k2) ); + BOOST_TEST( static_cast<bool>(k1 <= k2) ); + BOOST_TEST( static_cast<bool>(k <= k2) ); + BOOST_TEST( static_cast<bool>(k2 > k1) ); + BOOST_TEST( static_cast<bool>(k2 >= k1) ); + BOOST_TEST( static_cast<bool>(k2 >= k) ); + + cout << "Performed tests on MyChar objects.\n"; + + MyShort l1(1); + MyShort l2(2); + MyShort l; + + BOOST_TEST( l1.value() == 1 ); + BOOST_TEST( l2.value() == 2 ); + BOOST_TEST( l.value() == 0 ); + + cout << "Created MyShort objects.\n"; + + PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) ); + + BOOST_TEST( static_cast<bool>(l2 == l) ); + BOOST_TEST( static_cast<bool>(2 == l) ); + BOOST_TEST( static_cast<bool>(l2 == 2) ); + BOOST_TEST( static_cast<bool>(l == l2) ); + BOOST_TEST( static_cast<bool>(l1 != l2) ); + BOOST_TEST( static_cast<bool>(l1 != 2) ); + BOOST_TEST( static_cast<bool>(1 != l2) ); + BOOST_TEST( static_cast<bool>(l1 < l2) ); + BOOST_TEST( static_cast<bool>(1 < l2) ); + BOOST_TEST( static_cast<bool>(l1 < 2) ); + BOOST_TEST( static_cast<bool>(l1 <= l2) ); + BOOST_TEST( static_cast<bool>(1 <= l2) ); + BOOST_TEST( static_cast<bool>(l1 <= l) ); + BOOST_TEST( static_cast<bool>(l <= l2) ); + BOOST_TEST( static_cast<bool>(2 <= l2) ); + BOOST_TEST( static_cast<bool>(l <= 2) ); + BOOST_TEST( static_cast<bool>(l2 > l1) ); + BOOST_TEST( static_cast<bool>(2 > l1) ); + BOOST_TEST( static_cast<bool>(l2 > 1) ); + BOOST_TEST( static_cast<bool>(l2 >= l1) ); + BOOST_TEST( static_cast<bool>(2 >= l1) ); + BOOST_TEST( static_cast<bool>(l2 >= 1) ); + BOOST_TEST( static_cast<bool>(l2 >= l) ); + BOOST_TEST( static_cast<bool>(2 >= l) ); + BOOST_TEST( static_cast<bool>(l2 >= 2) ); + + cout << "Performed tests on MyShort objects.\n"; + + MyDoubleInt di1(1); + MyDoubleInt di2(2.); + MyDoubleInt half(0.5); + MyDoubleInt di; + MyDoubleInt tmp; + + BOOST_TEST( di1.value() == 1 ); + BOOST_TEST( di2.value() == 2 ); + BOOST_TEST( di2.value() == 2 ); + BOOST_TEST( di.value() == 0 ); + + cout << "Created MyDoubleInt objects.\n"; + + PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) ); + + BOOST_TEST( static_cast<bool>(di2 == di) ); + BOOST_TEST( static_cast<bool>(2 == di) ); + BOOST_TEST( static_cast<bool>(di == 2) ); + BOOST_TEST( static_cast<bool>(di1 < di2) ); + BOOST_TEST( static_cast<bool>(1 < di2) ); + BOOST_TEST( static_cast<bool>(di1 <= di2) ); + BOOST_TEST( static_cast<bool>(1 <= di2) ); + BOOST_TEST( static_cast<bool>(di2 > di1) ); + BOOST_TEST( static_cast<bool>(di2 > 1) ); + BOOST_TEST( static_cast<bool>(di2 >= di1) ); + BOOST_TEST( static_cast<bool>(di2 >= 1) ); + BOOST_TEST( static_cast<bool>(di1 / di2 == half) ); + BOOST_TEST( static_cast<bool>(di1 / 2 == half) ); + BOOST_TEST( static_cast<bool>(1 / di2 == half) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp/=2) == half) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp/=di2) == half) ); + BOOST_TEST( static_cast<bool>(di1 * di2 == di2) ); + BOOST_TEST( static_cast<bool>(di1 * 2 == di2) ); + BOOST_TEST( static_cast<bool>(1 * di2 == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp*=2) == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp*=di2) == di2) ); + BOOST_TEST( static_cast<bool>(di2 - di1 == di1) ); + BOOST_TEST( static_cast<bool>(di2 - 1 == di1) ); + BOOST_TEST( static_cast<bool>(2 - di1 == di1) ); + PRIVATE_EXPR_TEST( (tmp=di2), static_cast<bool>((tmp-=1) == di1) ); + PRIVATE_EXPR_TEST( (tmp=di2), static_cast<bool>((tmp-=di1) == di1) ); + BOOST_TEST( static_cast<bool>(di1 + di1 == di2) ); + BOOST_TEST( static_cast<bool>(di1 + 1 == di2) ); + BOOST_TEST( static_cast<bool>(1 + di1 == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp+=1) == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp+=di1) == di2) ); + + cout << "Performed tests on MyDoubleInt objects.\n"; + + MyLongInt li1(1); + MyLongInt li2(2); + MyLongInt li; + MyLongInt tmp2; + + BOOST_TEST( li1.value() == 1 ); + BOOST_TEST( li2.value() == 2 ); + BOOST_TEST( li.value() == 0 ); + + cout << "Created MyLongInt objects.\n"; + + PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) ); + + BOOST_TEST( static_cast<bool>(li2 == li) ); + BOOST_TEST( static_cast<bool>(2 == li) ); + BOOST_TEST( static_cast<bool>(li == 2) ); + BOOST_TEST( static_cast<bool>(li1 < li2) ); + BOOST_TEST( static_cast<bool>(1 < li2) ); + BOOST_TEST( static_cast<bool>(li1 <= li2) ); + BOOST_TEST( static_cast<bool>(1 <= li2) ); + BOOST_TEST( static_cast<bool>(li2 > li1) ); + BOOST_TEST( static_cast<bool>(li2 > 1) ); + BOOST_TEST( static_cast<bool>(li2 >= li1) ); + BOOST_TEST( static_cast<bool>(li2 >= 1) ); + BOOST_TEST( static_cast<bool>(li1 % li2 == li1) ); + BOOST_TEST( static_cast<bool>(li1 % 2 == li1) ); + BOOST_TEST( static_cast<bool>(1 % li2 == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2%=2) == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2%=li2) == li1) ); + BOOST_TEST( static_cast<bool>(li1 / li2 == 0) ); + BOOST_TEST( static_cast<bool>(li1 / 2 == 0) ); + BOOST_TEST( static_cast<bool>(1 / li2 == 0) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2/=2) == 0) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2/=li2) == 0) ); + BOOST_TEST( static_cast<bool>(li1 * li2 == li2) ); + BOOST_TEST( static_cast<bool>(li1 * 2 == li2) ); + BOOST_TEST( static_cast<bool>(1 * li2 == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2*=2) == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2*=li2) == li2) ); + BOOST_TEST( static_cast<bool>(li2 - li1 == li1) ); + BOOST_TEST( static_cast<bool>(li2 - 1 == li1) ); + BOOST_TEST( static_cast<bool>(2 - li1 == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li2), static_cast<bool>((tmp2-=1) == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li2), static_cast<bool>((tmp2-=li1) == li1) ); + BOOST_TEST( static_cast<bool>(li1 + li1 == li2) ); + BOOST_TEST( static_cast<bool>(li1 + 1 == li2) ); + BOOST_TEST( static_cast<bool>(1 + li1 == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2+=1) == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2+=li1) == li2) ); + + cout << "Performed tests on MyLongInt objects.\n"; + + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/result_of_test.cpp b/src/boost/libs/utility/test/result_of_test.cpp new file mode 100644 index 000000000..290043b37 --- /dev/null +++ b/src/boost/libs/utility/test/result_of_test.cpp @@ -0,0 +1,322 @@ +// Boost result_of library + +// Copyright Douglas Gregor 2003-2004. Use, modification and +// distribution is 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) + +// Examples: +// To run the default test: +// $ cd libs/utility/test && bjam +// To test decltype on g++ 2.7: +// $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE" + +#include <boost/config.hpp> + +// For more information, see http://www.boost.org/libs/utility +#include <boost/utility/result_of.hpp> +#include <utility> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> + +struct int_result_type +{ + typedef int result_type; + result_type operator()(float); +}; + +struct int_result_of +{ + template<typename F> struct result { typedef int type; }; + result<int_result_of(double)>::type operator()(double); + result<const int_result_of(double)>::type operator()(double) const; + result<int_result_of()>::type operator()(); + result<volatile int_result_of()>::type operator()() volatile; +}; + +struct int_result_type_and_float_result_of_and_char_return +{ + typedef int result_type; + template<typename F> struct result { typedef float type; }; + char operator()(char); +}; + +template<typename T> +struct int_result_type_template +{ + typedef int result_type; + result_type operator()(float); +}; + +template<typename T> +struct int_result_of_template +{ + template<typename F> struct result; + template<typename This, typename That> struct result<This(That)> { typedef int type; }; + typename result<int_result_of_template<T>(double)>::type operator()(double); + typename result<const int_result_of_template<T>(double)>::type operator()(double) const; + typename result<int_result_of_template<T>(double)>::type operator()(); + typename result<volatile int_result_of_template<T>(double)>::type operator()() volatile; +}; + +template<typename T> +struct int_result_type_and_float_result_of_and_char_return_template +{ + typedef int result_type; + template<typename F> struct result; + template<typename This, typename That> struct result<This(That)> { typedef float type; }; + char operator()(char); +}; + +template<typename T> +struct cv_overload_check {}; + +struct result_of_member_function_template +{ + template<typename F> struct result; + + template<typename This, typename That> struct result<This(That)> { typedef That type; }; + template<class T> typename result<result_of_member_function_template(T)>::type operator()(T); + + template<typename This, typename That> struct result<const This(That)> { typedef cv_overload_check<const That> type; }; + template<class T> typename result<const result_of_member_function_template(T)>::type operator()(T) const; + + template<typename This, typename That> struct result<volatile This(That)> { typedef cv_overload_check<volatile That> type; }; + template<class T> typename result<volatile result_of_member_function_template(T)>::type operator()(T) volatile; + + template<typename This, typename That> struct result<const volatile This(That)> { typedef cv_overload_check<const volatile That> type; }; + template<class T> typename result<const volatile result_of_member_function_template(T)>::type operator()(T) const volatile; + + template<typename This, typename That> struct result<This(That &, That)> { typedef That & type; }; + template<class T> typename result<result_of_member_function_template(T &, T)>::type operator()(T &, T); + + template<typename This, typename That> struct result<This(That const &, That)> { typedef That const & type; }; + template<class T> typename result<result_of_member_function_template(T const &, T)>::type operator()(T const &, T); + + template<typename This, typename That> struct result<This(That volatile &, That)> { typedef That volatile & type; }; + template<class T> typename result<result_of_member_function_template(T volatile &, T)>::type operator()(T volatile &, T); + + template<typename This, typename That> struct result<This(That const volatile &, That)> { typedef That const volatile & type; }; + template<class T> typename result<result_of_member_function_template(T const volatile &, T)>::type operator()(T const volatile &, T); +}; + +struct no_result_type_or_result +{ + short operator()(double); + cv_overload_check<const short> operator()(double) const; + cv_overload_check<volatile short> operator()(double) volatile; + cv_overload_check<const volatile short> operator()(double) const volatile; + int operator()(); + cv_overload_check<const int> operator()() const; + cv_overload_check<volatile int> operator()() volatile; + cv_overload_check<const volatile int> operator()() const volatile; +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + short operator()(int&&); + int operator()(int&); + long operator()(int const&); +#endif +}; + +template<typename T> +struct no_result_type_or_result_template +{ + short operator()(double); + cv_overload_check<const short> operator()(double) const; + cv_overload_check<volatile short> operator()(double) volatile; + cv_overload_check<const volatile short> operator()(double) const volatile; + int operator()(); + cv_overload_check<const int> operator()() const; + cv_overload_check<volatile int> operator()() volatile; + cv_overload_check<const volatile int> operator()() const volatile; +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + short operator()(int&&); + int operator()(int&); + long operator()(int const&); +#endif +}; + +// sfinae_tests are derived from example code from Joel de Guzman, +// which demonstrated the interaction between result_of and SFINAE. +template <typename F, typename Arg> +typename boost::result_of<F(Arg const&)>::type +sfinae_test(F f, Arg const& arg) +{ + return f(arg); +} + +template <typename F, typename Arg> +typename boost::result_of<F(Arg&)>::type +sfinae_test(F f, Arg& arg) +{ + return f(arg); +} + +int sfinae_test_f(int& i) +{ + return i; +} + +struct X {}; + +int main() +{ + using namespace boost; + + typedef int (*func_ptr)(float, double); + typedef int (&func_ref)(float, double); + typedef int (*func_ptr_0)(); + typedef int (&func_ref_0)(); + typedef void (*func_ptr_void)(float, double); + typedef void (&func_ref_void)(float, double); + typedef void (*func_ptr_void_0)(); + typedef void (&func_ref_void_0)(); + typedef int (X::*mem_func_ptr)(float); + typedef int (X::*mem_func_ptr_c)(float) const; + typedef int (X::*mem_func_ptr_v)(float) volatile; + typedef int (X::*mem_func_ptr_cv)(float) const volatile; + typedef int (X::*mem_func_ptr_0)(); + + BOOST_STATIC_ASSERT((is_same<result_of<int_result_type(float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_template<void>(float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of_template<void>(double)>::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type(float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<const int_result_of(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_template<void>(float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of_template<void>(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<const int_result_of_template<void>(double)>::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of(void)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of(void)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_of_template<void>(void)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of_template<void>(void)>::type, void>::value)); + + // Prior to decltype, result_of could not deduce the return type + // of nullary function objects unless they exposed a result_type. +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) + BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, int>::value)); +#else + BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, void>::value)); +#endif + + // Prior to decltype, result_of ignored a nested result<> if + // result_type was defined. After decltype, result_of deduces the + // actual return type of the function object, ignoring both + // result<> and result_type. +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) + BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, char>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, char>::value)); +#else + BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value)); +#endif + + BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(char, float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<func_ref(char, float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_0()>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<func_ref_0()>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void(char, float)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void(char, float)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void_0()>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void_0()>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr(X,char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_c(X,char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_v(X,char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_cv(X,char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_0(X)>::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(char, float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(char, float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_0()>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_0()>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void(char, float)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void(char, float)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void_0()>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void_0()>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr(X,char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_c(X,char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_v(X,char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_cv(X,char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_0(X)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(void)>::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(double)>::type, double>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int &, int)>::type, int &>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value)); + + BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(double)>::type, double>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int &, int)>::type, int &>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value)); + + typedef int (*pf_t)(int); + BOOST_STATIC_ASSERT((is_same<result_of<pf_t(int)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<pf_t const(int)>::type,int>::value)); + + BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t(int)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t const(int)>::type,int>::value)); + +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(double)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(double)>::type, cv_overload_check<const short> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(double)>::type, cv_overload_check<volatile short> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(double)>::type, cv_overload_check<const volatile short> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(void)>::type, cv_overload_check<const int> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(void)>::type, cv_overload_check<volatile int> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(void)>::type, cv_overload_check<const volatile int> >::value)); + + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(double)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const short> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<volatile short> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const volatile short> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const int> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<volatile int> >::value)); + BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const volatile int> >::value)); + + BOOST_STATIC_ASSERT((is_same<result_of<func_ptr&(char, float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<func_ptr const&(char, float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_of&(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<int_result_of const&(double)>::type, int>::value)); + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&&)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int const&)>::type, long>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&&)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int const&)>::type, long>::value)); +#endif +#endif + +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + int i = 123; + sfinae_test(sfinae_test_f, i); +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + + return 0; +} diff --git a/src/boost/libs/utility/test/string_ref_from_rvalue.cpp b/src/boost/libs/utility/test/string_ref_from_rvalue.cpp new file mode 100644 index 000000000..6ec8a5a2d --- /dev/null +++ b/src/boost/libs/utility/test/string_ref_from_rvalue.cpp @@ -0,0 +1,26 @@ +/* + Copyright (c) Marshall Clow 2017. + + 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) + + For more information, see http://www.boost.org +*/ + +#include <iostream> +#include <algorithm> +#include <string> + +#include <boost/utility/string_ref.hpp> + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +#error "Unsupported test" +#endif + +std::string makeatemp() { return "abc"; } + +int main() +{ + boost::basic_string_ref<char> sv(makeatemp()); + return 0; +} diff --git a/src/boost/libs/utility/test/string_ref_test1.cpp b/src/boost/libs/utility/test/string_ref_test1.cpp new file mode 100644 index 000000000..fc8890515 --- /dev/null +++ b/src/boost/libs/utility/test/string_ref_test1.cpp @@ -0,0 +1,110 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include <iostream> +#include <algorithm> +#include <string> + +#include <boost/utility/string_ref.hpp> + +#include <boost/core/lightweight_test.hpp> + +typedef boost::string_ref string_ref; + +// Should be equal +void interop ( const std::string &str, string_ref ref ) { +// BOOST_TEST ( str == ref ); + BOOST_TEST ( str.size () == ref.size ()); + BOOST_TEST ( std::equal ( str.begin (), str.end (), ref.begin ())); + BOOST_TEST ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ())); + } + +void null_tests ( const char *p ) { +// All zero-length string-refs should be equal + string_ref sr1; // NULL, 0 + string_ref sr2 ( NULL, 0 ); + string_ref sr3 ( p, 0 ); + string_ref sr4 ( p ); + sr4.clear (); + + BOOST_TEST ( sr1 == sr2 ); + BOOST_TEST ( sr1 == sr3 ); + BOOST_TEST ( sr2 == sr3 ); + BOOST_TEST ( sr1 == sr4 ); + } + +// make sure that substrings work just like strings +void test_substr ( const std::string &str ) { + const size_t sz = str.size (); + string_ref ref ( str ); + +// Substrings at the end + for ( size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( i ), ref.substr ( i )); + +// Substrings at the beginning + for ( size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( 0, i ), ref.substr ( 0, i )); + +// All possible substrings + for ( size_t i = 0; i < sz; ++i ) + for ( size_t j = i; j < sz; ++j ) + interop ( str.substr ( i, j ), ref.substr ( i, j )); + } + +// make sure that removing prefixes and suffixes work just like strings +void test_remove ( const std::string &str ) { + const size_t sz = str.size (); + std::string work; + string_ref ref; + + for ( size_t i = 1; i <= sz; ++i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( 0, i ); + ref.remove_prefix (i); + } + } + + for ( size_t i = 1; i < sz; ++ i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( work.size () - i, i ); + ref.remove_suffix (i); + } + } + } + +const char *test_strings [] = { + "", + "1", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "0123456789", + NULL + }; + +int main() +{ + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + interop ( *p, *p ); + test_substr ( *p ); + test_remove ( *p ); + null_tests ( *p ); + + p++; + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/string_ref_test2.cpp b/src/boost/libs/utility/test/string_ref_test2.cpp new file mode 100644 index 000000000..d73377517 --- /dev/null +++ b/src/boost/libs/utility/test/string_ref_test2.cpp @@ -0,0 +1,323 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include <iostream> +#include <cstring> // for std::strchr + +#include <boost/utility/string_ref.hpp> + +#include <boost/core/lightweight_test.hpp> + +typedef boost::string_ref string_ref; + +void ends_with ( const char *arg ) { + const size_t sz = std::strlen ( arg ); + string_ref sr ( arg ); + string_ref sr2 ( arg ); + const char *p = arg; + + while ( *p ) { + BOOST_TEST ( sr.ends_with ( p )); + ++p; + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + sr2 = arg; + while ( !sr2.empty ()) { + BOOST_TEST ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + char ch = sz == 0 ? '\0' : arg [ sz - 1 ]; + sr2 = arg; + if ( sz > 0 ) + BOOST_TEST ( sr2.ends_with ( ch )); + BOOST_TEST ( !sr2.ends_with ( ++ch )); + BOOST_TEST ( sr2.ends_with ( string_ref ())); + } + +void starts_with ( const char *arg ) { + const size_t sz = std::strlen ( arg ); + string_ref sr ( arg ); + string_ref sr2 ( arg ); + const char *p = arg + std::strlen ( arg ) - 1; + while ( p >= arg ) { + std::string foo ( arg, p + 1 ); + BOOST_TEST ( sr.starts_with ( foo )); + --p; + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.starts_with ( sr2 )); + sr2.remove_suffix (1); + } + + char ch = *arg; + sr2 = arg; + if ( sz > 0 ) + BOOST_TEST ( sr2.starts_with ( ch )); + BOOST_TEST ( !sr2.starts_with ( ++ch )); + BOOST_TEST ( sr2.starts_with ( string_ref ())); + } + +void reverse ( const char *arg ) { +// Round trip + string_ref sr1 ( arg ); + std::string string1 ( sr1.rbegin (), sr1.rend ()); + string_ref sr2 ( string1 ); + std::string string2 ( sr2.rbegin (), sr2.rend ()); + + BOOST_TEST ( std::equal ( sr2.rbegin (), sr2.rend (), arg )); + BOOST_TEST ( string2 == arg ); + BOOST_TEST ( std::equal ( sr1.begin (), sr1.end (), string2.begin ())); + } + +// This helper function eliminates signed vs. unsigned warnings +string_ref::size_type ptr_diff ( const char *res, const char *base ) { + BOOST_TEST ( res >= base ); + return static_cast<string_ref::size_type> ( res - base ); + } + +void find ( const char *arg ) { + string_ref sr1; + string_ref sr2; + const char *p; + +// When we search for the empty string, we find it at position 0 + BOOST_TEST ( sr1.find (sr2) == 0 ); + BOOST_TEST ( sr1.rfind(sr2) == 0 ); + +// Look for each character in the string(searching from the start) + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos = sr1.find(*p); + BOOST_TEST ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg ))); + ++p; + } + +// Look for each character in the string (searching from the end) + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos = sr1.rfind(*p); + BOOST_TEST ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg ))); + ++p; + } + +// Look for pairs on characters (searching from the start) + sr1 = arg; + p = arg; + while ( *p && *(p+1)) { + string_ref sr3 ( p, 2 ); + string_ref::size_type pos = sr1.find ( sr3 ); + BOOST_TEST ( pos != string_ref::npos && pos <= static_cast<string_ref::size_type>( p - arg )); + p++; + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_ref::size_type pos = sr1.find(ch); + const char *strp = std::strchr ( arg, ch ); + BOOST_TEST (( strp == NULL ) == ( pos == string_ref::npos )); + if ( strp != NULL ) + BOOST_TEST ( ptr_diff ( strp, arg ) == pos ); + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_ref::size_type pos = sr1.rfind(ch); + const char *strp = std::strrchr ( arg, ch ); + BOOST_TEST (( strp == NULL ) == ( pos == string_ref::npos )); + if ( strp != NULL ) + BOOST_TEST ( ptr_diff ( strp, arg ) == pos ); + } + + +// Find everything at the start + p = arg; + sr1 = arg; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find(*p); + BOOST_TEST ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + +// Find everything at the end + sr1 = arg; + p = arg + std::strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.rfind(*p); + BOOST_TEST ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Find everything at the start + sr1 = arg; + p = arg; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find_first_of(*p); + BOOST_TEST ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + + +// Find everything at the end + sr1 = arg; + p = arg + std::strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find_last_of(*p); + BOOST_TEST ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Basic sanity checking for "find_first_of / find_first_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_TEST ( sr1.find_first_of ( sr2 ) == 0 ); + BOOST_TEST ( sr1.find_first_not_of ( sr2 ) == string_ref::npos ); + sr1.remove_prefix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos1 = sr1.find_first_of(*p); + string_ref::size_type pos2 = sr1.find_first_not_of(*p); + BOOST_TEST ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg )); + if ( pos2 != string_ref::npos ) { + for ( size_t i = 0 ; i < pos2; ++i ) + BOOST_TEST ( sr1[i] == *p ); + BOOST_TEST ( sr1 [ pos2 ] != *p ); + } + + BOOST_TEST ( pos2 != pos1 ); + ++p; + } + +// Basic sanity checking for "find_last_of / find_last_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_TEST ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 )); + BOOST_TEST ( sr1.find_last_not_of ( sr2 ) == string_ref::npos ); + sr1.remove_suffix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos1 = sr1.find_last_of(*p); + string_ref::size_type pos2 = sr1.find_last_not_of(*p); + BOOST_TEST ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg )); + BOOST_TEST ( pos2 == string_ref::npos || pos1 < sr1.size ()); + if ( pos2 != string_ref::npos ) { + for ( size_t i = sr1.size () -1 ; i > pos2; --i ) + BOOST_TEST ( sr1[i] == *p ); + BOOST_TEST ( sr1 [ pos2 ] != *p ); + } + + BOOST_TEST ( pos2 != pos1 ); + ++p; + } + + } + + +void to_string ( const char *arg ) { + string_ref sr1; + std::string str1; + std::string str2; + + str1.assign ( arg ); + sr1 = arg; +// str2 = sr1.to_string<std::allocator<char> > (); + str2 = sr1.to_string (); + BOOST_TEST ( str1 == str2 ); + +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + std::string str3 = static_cast<std::string> ( sr1 ); + BOOST_TEST ( str1 == str3 ); +#endif + } + +void compare ( const char *arg ) { + string_ref sr1; + std::string str1; + std::string str2 = str1; + + str1.assign ( arg ); + sr1 = arg; + BOOST_TEST ( sr1 == sr1); // compare string_ref and string_ref + BOOST_TEST ( sr1 == str1); // compare string and string_ref + BOOST_TEST ( str1 == sr1 ); // compare string_ref and string + BOOST_TEST ( sr1 == arg ); // compare string_ref and pointer + BOOST_TEST ( arg == sr1 ); // compare pointer and string_ref + + if ( sr1.size () > 0 ) { + (*str1.rbegin())++; + BOOST_TEST ( sr1 != str1 ); + BOOST_TEST ( str1 != sr1 ); + BOOST_TEST ( sr1 < str1 ); + BOOST_TEST ( sr1 <= str1 ); + BOOST_TEST ( str1 > sr1 ); + BOOST_TEST ( str1 >= sr1 ); + + (*str1.rbegin()) -= 2; + BOOST_TEST ( sr1 != str1 ); + BOOST_TEST ( str1 != sr1 ); + BOOST_TEST ( sr1 > str1 ); + BOOST_TEST ( sr1 >= str1 ); + BOOST_TEST ( str1 < sr1 ); + BOOST_TEST ( str1 <= sr1 ); + } + } + +const char *test_strings [] = { + "", + "0", + "abc", + "AAA", // all the same + "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf", + "abc\0asdfadsfasf", + NULL + }; + +int main() +{ + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + starts_with ( *p ); + ends_with ( *p ); + reverse ( *p ); + find ( *p ); + to_string ( *p ); + compare ( *p ); + + p++; + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/string_ref_test_io.cpp b/src/boost/libs/utility/test/string_ref_test_io.cpp new file mode 100644 index 000000000..3609f915f --- /dev/null +++ b/src/boost/libs/utility/test/string_ref_test_io.cpp @@ -0,0 +1,184 @@ +/* + * Copyright Andrey Semashev 2013. + * 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) + */ +/*! + * \file string_ref_test_io.cpp + * \author Andrey Semashev + * \date 26.05.2013 + * + * \brief This header contains tests for stream operations of \c basic_string_ref. + */ + +#include <boost/utility/string_ref.hpp> + +#include <iomanip> +#include <sstream> +#include <algorithm> +#include <iterator> +#include <string> + +#include <boost/config.hpp> +#include <boost/core/lightweight_test.hpp> + +/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available. +*/ + +static const char* test_strings[] = +{ + "begin", + "abcd", + "end" +}; + +//! The context with test data for particular character type +template< typename CharT > +struct context +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + + string_type begin, abcd, end; + + context() + { + boost::string_ref str = test_strings[0]; + std::copy(str.begin(), str.end(), std::back_inserter(begin)); + + str = test_strings[1]; + std::copy(str.begin(), str.end(), std::back_inserter(abcd)); + + str = test_strings[2]; + std::copy(str.begin(), str.end(), std::back_inserter(end)); + } +}; + +// Test regular output +template<class CharT> +void test_string_ref_output() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + ostream_type strm; + strm << string_ref_type(ctx.abcd); + BOOST_TEST(strm.str() == ctx.abcd); +} + +// Test support for padding +template<class CharT> +void test_padding() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + // Test for padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Test for long padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(100) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Test that short width does not truncate the string + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(1) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } +} + +// Test support for padding fill +template<class CharT> +void test_padding_fill() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + ostream_type strm_ref; + strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); +} + +// Test support for alignment +template<class CharT> +void test_alignment() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + // Left alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::left << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Right alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::right << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } +} + +template<class CharT> +void test() +{ + test_string_ref_output<CharT>(); + test_padding<CharT>(); + test_padding_fill<CharT>(); + test_alignment<CharT>(); +} + +int main() +{ + test<char>(); + test<wchar_t>(); + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/string_view_constexpr_test1.cpp b/src/boost/libs/utility/test/string_view_constexpr_test1.cpp new file mode 100644 index 000000000..d116e12d6 --- /dev/null +++ b/src/boost/libs/utility/test/string_view_constexpr_test1.cpp @@ -0,0 +1,115 @@ +/* + Copyright (c) Marshall Clow 2017-2017. + + 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) + + For more information, see http://www.boost.org +*/ + +#include <new> // for placement new +#include <iostream> +#include <cstddef> // for NULL, std::size_t, std::ptrdiff_t +#include <cstring> // for std::strchr and std::strcmp +#include <cstdlib> // for std::malloc and std::free +#include <cstdio> // for EOF + +#include <boost/config.hpp> +#include <boost/utility/string_view.hpp> + +#if __cplusplus >= 201402L +struct constexpr_char_traits +{ + typedef char char_type; + typedef int int_type; + typedef std::streamoff off_type; + typedef std::streampos pos_type; + typedef std::mbstate_t state_type; + + static void assign(char_type& c1, const char_type& c2) noexcept { c1 = c2; } + static constexpr bool eq(char_type c1, char_type c2) noexcept { return c1 == c2; } + static constexpr bool lt(char_type c1, char_type c2) noexcept { return c1 < c2; } + + static constexpr int compare(const char_type* s1, const char_type* s2, size_t n) noexcept; + static constexpr size_t length(const char_type* s) noexcept; + static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a) noexcept; + static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n) noexcept; + static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n) noexcept; + static constexpr char_type* assign(char_type* s, size_t n, char_type a) noexcept; + + static constexpr int_type not_eof(int_type c) noexcept { return eq_int_type(c, eof()) ? ~eof() : c; } + static constexpr char_type to_char_type(int_type c) noexcept { return char_type(c); } + static constexpr int_type to_int_type(char_type c) noexcept { return int_type(c); } + static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept { return c1 == c2; } + static constexpr int_type eof() noexcept { return EOF; } +}; + +// yields: +// 0 if for each i in [0,n), X::eq(s1[i],s2[i]) is true; +// else, a negative value if, for some j in [0,n), X::lt(s1[j],s2[j]) is true and +// for each i in [0,j) X::eq(s2[i],s2[i]) is true; +// else a positive value. +constexpr int constexpr_char_traits::compare(const char_type* s1, const char_type* s2, size_t n) noexcept +{ + for (; n != 0; --n, ++s1, ++s2) + { + if (lt(*s1, *s2)) + return -1; + if (lt(*s2, *s1)) + return 1; + } + return 0; +} + +// yields: the smallest i such that X::eq(s[i],charT()) is true. +constexpr size_t constexpr_char_traits::length(const char_type* s) noexcept +{ + size_t len = 0; + for (; !eq(*s, char_type(0)); ++s) + ++len; + return len; +} + +typedef boost::basic_string_view<char, constexpr_char_traits> string_view; + +int main() +{ + constexpr string_view sv1; + constexpr string_view sv2{"abc", 3}; // ptr, len + constexpr string_view sv3{"def"}; // ptr + + constexpr const char *s1 = ""; + constexpr const char *s2 = "abc"; + + static_assert( (sv1 == sv1), "" ); + + static_assert(!(sv1 == sv2), "" ); + static_assert( (sv1 != sv2), "" ); + static_assert( (sv1 < sv2), "" ); + static_assert( (sv1 <= sv2), "" ); + static_assert(!(sv1 > sv2), "" ); + static_assert(!(sv1 >= sv2), "" ); + + static_assert(!(s1 == sv2), "" ); + static_assert( (s1 != sv2), "" ); + static_assert( (s1 < sv2), "" ); + static_assert( (s1 <= sv2), "" ); + static_assert(!(s1 > sv2), "" ); + static_assert(!(s1 >= sv2), "" ); + + static_assert(!(sv1 == s2), "" ); + static_assert( (sv1 != s2), "" ); + static_assert( (sv1 < s2), "" ); + static_assert( (sv1 <= s2), "" ); + static_assert(!(sv1 > s2), "" ); + static_assert(!(sv1 >= s2), "" ); + + static_assert( sv1.compare(sv2) < 0, "" ); + static_assert( sv1.compare(sv1) == 0, "" ); + static_assert( sv3.compare(sv1) > 0, "" ); + + static_assert( sv1.compare(s2) < 0, "" ); + static_assert( sv1.compare(s1) == 0, "" ); + static_assert( sv3.compare(s1) > 0, "" ); +} +#endif diff --git a/src/boost/libs/utility/test/string_view_from_rvalue.cpp b/src/boost/libs/utility/test/string_view_from_rvalue.cpp new file mode 100644 index 000000000..a76493959 --- /dev/null +++ b/src/boost/libs/utility/test/string_view_from_rvalue.cpp @@ -0,0 +1,26 @@ +/* + Copyright (c) Marshall Clow 2017. + + 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) + + For more information, see http://www.boost.org +*/ + +#include <iostream> +#include <algorithm> +#include <string> + +#include <boost/utility/string_view.hpp> + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +#error "Unsupported test" +#endif + +std::string makeatemp() { return "abc"; } + +int main() +{ + boost::basic_string_view<char> sv(makeatemp()); + return 0; +} diff --git a/src/boost/libs/utility/test/string_view_test1.cpp b/src/boost/libs/utility/test/string_view_test1.cpp new file mode 100644 index 000000000..c35bbfac6 --- /dev/null +++ b/src/boost/libs/utility/test/string_view_test1.cpp @@ -0,0 +1,120 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include <iostream> +#include <algorithm> +#include <string> + +#include <boost/utility/string_view.hpp> +#include <boost/container_hash/hash.hpp> + +#include <boost/core/lightweight_test.hpp> + +typedef boost::string_view string_view; + +// Should be equal +void interop ( const std::string &str, string_view ref ) { +// BOOST_TEST ( str == ref ); + BOOST_TEST ( str.size () == ref.size ()); + BOOST_TEST ( std::equal ( str.begin (), str.end (), ref.begin ())); + BOOST_TEST ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ())); + } + +void null_tests ( const char *p ) { +// All zero-length string-refs should be equal + string_view sr1; // NULL, 0 + string_view sr2 ( NULL, 0 ); + string_view sr3 ( p, 0 ); + string_view sr4 ( p ); + sr4.clear (); + + BOOST_TEST ( sr1 == sr2 ); + BOOST_TEST ( sr1 == sr3 ); + BOOST_TEST ( sr2 == sr3 ); + BOOST_TEST ( sr1 == sr4 ); + } + +// make sure that substrings work just like strings +void test_substr ( const std::string &str ) { + const size_t sz = str.size (); + string_view ref ( str ); + +// Substrings at the end + for ( size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( i ), ref.substr ( i )); + +// Substrings at the beginning + for ( size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( 0, i ), ref.substr ( 0, i )); + +// All possible substrings + for ( size_t i = 0; i < sz; ++i ) + for ( size_t j = i; j < sz; ++j ) + interop ( str.substr ( i, j ), ref.substr ( i, j )); + } + +// make sure that removing prefixes and suffixes work just like strings +void test_remove ( const std::string &str ) { + const size_t sz = str.size (); + std::string work; + string_view ref; + + for ( size_t i = 1; i <= sz; ++i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( 0, i ); + ref.remove_prefix (i); + } + } + + for ( size_t i = 1; i < sz; ++ i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( work.size () - i, i ); + ref.remove_suffix (i); + } + } + } + +void test_hash(const std::string& str) { + string_view ref = str; + BOOST_TEST(boost::hash_value(ref) == boost::hash_value(str)); + boost::hash<std::string> hstr; + boost::hash<string_view> hsv; + BOOST_TEST(hsv(ref) == hstr(str)); + } + +const char *test_strings [] = { + "", + "1", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "0123456789", + NULL + }; + +int main() +{ + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + interop ( *p, *p ); + test_substr ( *p ); + test_remove ( *p ); + null_tests ( *p ); + test_hash( *p ); + + p++; + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/string_view_test2.cpp b/src/boost/libs/utility/test/string_view_test2.cpp new file mode 100644 index 000000000..135fd1aa3 --- /dev/null +++ b/src/boost/libs/utility/test/string_view_test2.cpp @@ -0,0 +1,410 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include <new> // for placement new +#include <iostream> +#include <cstddef> // for NULL, std::size_t, std::ptrdiff_t +#include <cstring> // for std::strchr and std::strcmp +#include <cstdlib> // for std::malloc and std::free + +#include <boost/utility/string_view.hpp> +#include <boost/config.hpp> + +#include <boost/core/lightweight_test.hpp> + +typedef boost::string_view string_view; + +void ends_with ( const char *arg ) { + const size_t sz = std::strlen ( arg ); + string_view sr ( arg ); + string_view sr2 ( arg ); + const char *p = arg; + + while ( *p ) { + BOOST_TEST ( sr.ends_with ( p )); + ++p; + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + sr2 = arg; + while ( !sr2.empty ()) { + BOOST_TEST ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + char ch = sz == 0 ? '\0' : arg [ sz - 1 ]; + sr2 = arg; + if ( sz > 0 ) + BOOST_TEST ( sr2.ends_with ( ch )); + BOOST_TEST ( !sr2.ends_with ( ++ch )); + BOOST_TEST ( sr2.ends_with ( string_view())); + } + +void starts_with ( const char *arg ) { + const size_t sz = std::strlen ( arg ); + string_view sr ( arg ); + string_view sr2 ( arg ); + const char *p = arg + std::strlen ( arg ) - 1; + while ( p >= arg ) { + std::string foo ( arg, p + 1 ); + BOOST_TEST ( sr.starts_with ( foo )); + --p; + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.starts_with ( sr2 )); + sr2.remove_suffix (1); + } + + char ch = *arg; + sr2 = arg; + if ( sz > 0 ) + BOOST_TEST ( sr2.starts_with ( ch )); + BOOST_TEST ( !sr2.starts_with ( ++ch )); + BOOST_TEST ( sr2.starts_with ( string_view ())); + } + +void reverse ( const char *arg ) { +// Round trip + string_view sr1 ( arg ); + std::string string1 ( sr1.rbegin (), sr1.rend ()); + string_view sr2 ( string1 ); + std::string string2 ( sr2.rbegin (), sr2.rend ()); + + BOOST_TEST ( std::equal ( sr2.rbegin (), sr2.rend (), arg )); + BOOST_TEST ( string2 == arg ); + BOOST_TEST ( std::equal ( sr1.begin (), sr1.end (), string2.begin ())); + } + +// This helper function eliminates signed vs. unsigned warnings +string_view::size_type ptr_diff ( const char *res, const char *base ) { + BOOST_TEST ( res >= base ); + return static_cast<string_view::size_type> ( res - base ); + } + +void find ( const char *arg ) { + string_view sr1; + string_view sr2; + const char *p; + +// When we search for the empty string, we find it at position 0 + BOOST_TEST ( sr1.find (sr2) == 0 ); + BOOST_TEST ( sr1.rfind(sr2) == 0 ); + +// Look for each character in the string(searching from the start) + p = arg; + sr1 = arg; + while ( *p ) { + string_view::size_type pos = sr1.find(*p); + BOOST_TEST ( pos != string_view::npos && ( pos <= ptr_diff ( p, arg ))); + ++p; + } + +// Look for each character in the string (searching from the end) + p = arg; + sr1 = arg; + while ( *p ) { + string_view::size_type pos = sr1.rfind(*p); + BOOST_TEST ( pos != string_view::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg ))); + ++p; + } + +// Look for pairs on characters (searching from the start) + sr1 = arg; + p = arg; + while ( *p && *(p+1)) { + string_view sr3 ( p, 2 ); + string_view::size_type pos = sr1.find ( sr3 ); + BOOST_TEST ( pos != string_view::npos && pos <= static_cast<string_view::size_type>( p - arg )); + p++; + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_view::size_type pos = sr1.find(ch); + const char *strp = std::strchr ( arg, ch ); + BOOST_TEST (( strp == NULL ) == ( pos == string_view::npos )); + if ( strp != NULL ) + BOOST_TEST ( ptr_diff ( strp, arg ) == pos ); + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_view::size_type pos = sr1.rfind(ch); + const char *strp = std::strrchr ( arg, ch ); + BOOST_TEST (( strp == NULL ) == ( pos == string_view::npos )); + if ( strp != NULL ) + BOOST_TEST ( ptr_diff ( strp, arg ) == pos ); + } + + +// Find everything at the start + p = arg; + sr1 = arg; + while ( !sr1.empty ()) { + string_view::size_type pos = sr1.find(*p); + BOOST_TEST ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + +// Find everything at the end + sr1 = arg; + p = arg + std::strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_view::size_type pos = sr1.rfind(*p); + BOOST_TEST ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Find everything at the start + sr1 = arg; + p = arg; + while ( !sr1.empty ()) { + string_view::size_type pos = sr1.find_first_of(*p); + BOOST_TEST ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + + +// Find everything at the end + sr1 = arg; + p = arg + std::strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_view::size_type pos = sr1.find_last_of(*p); + BOOST_TEST ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Basic sanity checking for "find_first_of / find_first_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_TEST ( sr1.find_first_of ( sr2 ) == 0 ); + BOOST_TEST ( sr1.find_first_not_of ( sr2 ) == string_view::npos ); + sr1.remove_prefix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_view::size_type pos1 = sr1.find_first_of(*p); + string_view::size_type pos2 = sr1.find_first_not_of(*p); + BOOST_TEST ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg )); + if ( pos2 != string_view::npos ) { + for ( size_t i = 0 ; i < pos2; ++i ) + BOOST_TEST ( sr1[i] == *p ); + BOOST_TEST ( sr1 [ pos2 ] != *p ); + } + + BOOST_TEST ( pos2 != pos1 ); + ++p; + } + +// Basic sanity checking for "find_last_of / find_last_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_TEST ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 )); + BOOST_TEST ( sr1.find_last_not_of ( sr2 ) == string_view::npos ); + sr1.remove_suffix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_view::size_type pos1 = sr1.find_last_of(*p); + string_view::size_type pos2 = sr1.find_last_not_of(*p); + BOOST_TEST ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg )); + BOOST_TEST ( pos2 == string_view::npos || pos1 < sr1.size ()); + if ( pos2 != string_view::npos ) { + for ( size_t i = sr1.size () -1 ; i > pos2; --i ) + BOOST_TEST ( sr1[i] == *p ); + BOOST_TEST ( sr1 [ pos2 ] != *p ); + } + + BOOST_TEST ( pos2 != pos1 ); + ++p; + } + + } + +template <typename T> +class custom_allocator { +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + + template<class U> + struct rebind { + typedef custom_allocator<U> other; + }; + + custom_allocator() BOOST_NOEXCEPT {} + template <typename U> + custom_allocator(custom_allocator<U> const&) BOOST_NOEXCEPT {} + + pointer allocate(size_type n) const { + return static_cast<pointer>(std::malloc(sizeof(value_type) * n)); + } + void deallocate(pointer p, size_type) const BOOST_NOEXCEPT { + std::free(p); + } + + pointer address(reference value) const BOOST_NOEXCEPT { + return &value; + } + + const_pointer address(const_reference value) const BOOST_NOEXCEPT { + return &value; + } + + BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { + return (~(size_type)0u) / sizeof(value_type); + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template <class U, class... Args> + void construct(U* ptr, Args&&... args) const { + ::new((void*)ptr) U(static_cast<Args&&>(args)...); + } +#else + template <class U, class V> + void construct(U* ptr, V&& value) const { + ::new((void*)ptr) U(static_cast<V&&>(value)); + } +#endif +#else + template <class U, class V> + void construct(U* ptr, const V& value) const { + ::new((void*)ptr) U(value); + } +#endif + + template <class U> + void construct(U* ptr) const { + ::new((void*)ptr) U(); + } + + template <class U> + void destroy(U* ptr) const { + (void)ptr; + ptr->~U(); + } + }; + +template <typename T, typename U> +BOOST_CONSTEXPR bool operator==(const custom_allocator<T> &, const custom_allocator<U> &) BOOST_NOEXCEPT { + return true; + } +template <typename T, typename U> +BOOST_CONSTEXPR bool operator!=(const custom_allocator<T> &, const custom_allocator<U> &) BOOST_NOEXCEPT { + return false; + } + +void to_string ( const char *arg ) { + string_view sr1; + std::string str1; + std::string str2; + + str1.assign ( arg ); + sr1 = arg; +// str2 = sr1.to_string<std::allocator<char> > (); + str2 = sr1.to_string (); + BOOST_TEST ( str1 == str2 ); + + std::basic_string<char, std::char_traits<char>, custom_allocator<char> > str3 = sr1.to_string(custom_allocator<char>()); + BOOST_TEST ( std::strcmp(str1.c_str(), str3.c_str()) == 0 ); + +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + std::string str4 = static_cast<std::string> ( sr1 ); + BOOST_TEST ( str1 == str4 ); +#endif + } + +void compare ( const char *arg ) { + string_view sr1; + std::string str1; + std::string str2 = str1; + + str1.assign ( arg ); + sr1 = arg; + BOOST_TEST ( sr1 == sr1); // compare string_view and string_view + BOOST_TEST ( sr1 == str1); // compare string and string_view + BOOST_TEST ( str1 == sr1 ); // compare string_view and string + BOOST_TEST ( sr1 == arg ); // compare string_view and pointer + BOOST_TEST ( arg == sr1 ); // compare pointer and string_view + + if ( sr1.size () > 0 ) { + (*str1.rbegin())++; + BOOST_TEST ( sr1 != str1 ); + BOOST_TEST ( str1 != sr1 ); + BOOST_TEST ( sr1 < str1 ); + BOOST_TEST ( sr1 <= str1 ); + BOOST_TEST ( str1 > sr1 ); + BOOST_TEST ( str1 >= sr1 ); + + (*str1.rbegin()) -= 2; + BOOST_TEST ( sr1 != str1 ); + BOOST_TEST ( str1 != sr1 ); + BOOST_TEST ( sr1 > str1 ); + BOOST_TEST ( sr1 >= str1 ); + BOOST_TEST ( str1 < sr1 ); + BOOST_TEST ( str1 <= sr1 ); + } + } + +const char *test_strings [] = { + "", + "0", + "abc", + "AAA", // all the same + "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf", + "abc\0asdfadsfasf", + NULL + }; + +int main() +{ + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + starts_with ( *p ); + ends_with ( *p ); + reverse ( *p ); + find ( *p ); + to_string ( *p ); + compare ( *p ); + + p++; + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/string_view_test_io.cpp b/src/boost/libs/utility/test/string_view_test_io.cpp new file mode 100644 index 000000000..416ff3383 --- /dev/null +++ b/src/boost/libs/utility/test/string_view_test_io.cpp @@ -0,0 +1,184 @@ +/* + * Copyright Andrey Semashev 2013. + * 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) + */ +/*! + * \file string_ref_test_io.cpp + * \author Andrey Semashev + * \date 26.05.2013 + * + * \brief This header contains tests for stream operations of \c basic_string_ref. + */ + +#include <boost/utility/string_view.hpp> + +#include <iomanip> +#include <sstream> +#include <algorithm> +#include <iterator> +#include <string> + +#include <boost/config.hpp> +#include <boost/core/lightweight_test.hpp> + +/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available. +*/ + +static const char* test_strings[] = +{ + "begin", + "abcd", + "end" +}; + +//! The context with test data for particular character type +template< typename CharT > +struct context +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + + string_type begin, abcd, end; + + context() + { + boost::string_view str = test_strings[0]; + std::copy(str.begin(), str.end(), std::back_inserter(begin)); + + str = test_strings[1]; + std::copy(str.begin(), str.end(), std::back_inserter(abcd)); + + str = test_strings[2]; + std::copy(str.begin(), str.end(), std::back_inserter(end)); + } +}; + +// Test regular output +template<class CharT> +void test_string_view_output() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_view< char_type > string_view_type; + + context< char_type > ctx; + + ostream_type strm; + strm << string_view_type(ctx.abcd); + BOOST_TEST(strm.str() == ctx.abcd); +} + +// Test support for padding +template<class CharT> +void test_padding() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_view< char_type > string_view_type; + + context< char_type > ctx; + + // Test for padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(8) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Test for long padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(100) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Test that short width does not truncate the string + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(1) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } +} + +// Test support for padding fill +template<class CharT> +void test_padding_fill() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_view< char_type > string_view_type; + + context< char_type > ctx; + + ostream_type strm_ref; + strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); +} + +// Test support for alignment +template<class CharT> +void test_alignment() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_view< char_type > string_view_type; + + context< char_type > ctx; + + // Left alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::left << std::setw(8) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Right alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::right << std::setw(8) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } +} + +template<class CharT> +void test() +{ + test_string_view_output<CharT>(); + test_padding<CharT>(); + test_padding_fill<CharT>(); + test_alignment<CharT>(); +} + +int main() +{ + test<char>(); + test<wchar_t>(); + return boost::report_errors(); +} diff --git a/src/boost/libs/utility/test/value_init_test.cpp b/src/boost/libs/utility/test/value_init_test.cpp new file mode 100644 index 000000000..ed7ec3d5b --- /dev/null +++ b/src/boost/libs/utility/test/value_init_test.cpp @@ -0,0 +1,371 @@ +// Copyright 2002-2008, Fernando Luis Cacciola Carballal. +// +// 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) +// +// Test program for "boost/utility/value_init.hpp" +// +// 21 Ago 2002 (Created) Fernando Cacciola +// 15 Jan 2008 (Added tests regarding compiler issues) Fernando Cacciola, Niels Dekker +// 23 May 2008 (Added tests regarding initialized_value) Niels Dekker +// 21 Ago 2008 (Added swap test) Niels Dekker + +#include <cstring> // For memcmp. +#include <iostream> +#include <string> + +#include "boost/utility/value_init.hpp" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#include <boost/core/lightweight_test.hpp> + +// +// Sample POD type +// +struct POD +{ + POD () : f(0), c(0), i(0){} + + POD ( char c_, int i_, float f_ ) : f(f_), c(c_), i(i_) {} + + friend std::ostream& operator << ( std::ostream& os, POD const& pod ) + { return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; } + + friend bool operator == ( POD const& lhs, POD const& rhs ) + { return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; } + + float f; + char c; + int i; +} ; + +// +// Sample non POD type +// +struct NonPODBase +{ + virtual ~NonPODBase() {} +} ; +struct NonPOD : NonPODBase +{ + NonPOD () : id() {} + explicit NonPOD ( std::string const& id_) : id(id_) {} + + friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod ) + { return os << '(' << npod.id << ')' ; } + + friend bool operator == ( NonPOD const& lhs, NonPOD const& rhs ) + { return lhs.id == rhs.id ; } + + std::string id ; +} ; + +// +// Sample aggregate POD struct type +// Some compilers do not correctly value-initialize such a struct, for example: +// Borland C++ Report #51854, "Value-initialization: POD struct should be zero-initialized " +// http://qc.codegear.com/wc/qcmain.aspx?d=51854 +// +struct AggregatePODStruct +{ + float f; + char c; + int i; +}; + +bool operator == ( AggregatePODStruct const& lhs, AggregatePODStruct const& rhs ) +{ return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; } + +// +// An aggregate struct that contains an std::string and an int. +// Pavel Kuznetsov (MetaCommunications Engineering) used a struct like +// this to reproduce the Microsoft Visual C++ compiler bug, reported as +// Feedback ID 100744, "Value-initialization in new-expression" +// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 +// +struct StringAndInt +{ + std::string s; + int i; +}; + +bool operator == ( StringAndInt const& lhs, StringAndInt const& rhs ) +{ return lhs.s == rhs.s && lhs.i == rhs.i ; } + + +// +// A struct that has an explicit (user defined) destructor. +// Some compilers do not correctly value-initialize such a struct, for example: +// Microsoft Visual C++, Feedback ID 100744, "Value-initialization in new-expression" +// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 +// +struct StructWithDestructor +{ + int i; + ~StructWithDestructor() {} +}; + +bool operator == ( StructWithDestructor const& lhs, StructWithDestructor const& rhs ) +{ return lhs.i == rhs.i ; } + + +// +// A struct that has a virtual function. +// Some compilers do not correctly value-initialize such a struct either, for example: +// Microsoft Visual C++, Feedback ID 100744, "Value-initialization in new-expression" +// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 +// +struct StructWithVirtualFunction +{ + int i; + virtual void VirtualFunction(); +}; + +void StructWithVirtualFunction::VirtualFunction() +{ +} + +bool operator == ( StructWithVirtualFunction const& lhs, StructWithVirtualFunction const& rhs ) +{ return lhs.i == rhs.i ; } + + +// +// A struct that is derived from an aggregate POD struct. +// Some compilers do not correctly value-initialize such a struct, for example: +// GCC Bugzilla Bug 30111, "Value-initialization of POD base class doesn't initialize members", +// reported by Jonathan Wakely, http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 +// +struct DerivedFromAggregatePODStruct : AggregatePODStruct +{ + DerivedFromAggregatePODStruct() : AggregatePODStruct() {} +}; + +// +// A struct that wraps an aggregate POD struct as data member. +// +struct AggregatePODStructWrapper +{ + AggregatePODStructWrapper() : dataMember() {} + AggregatePODStruct dataMember; +}; + +bool operator == ( AggregatePODStructWrapper const& lhs, AggregatePODStructWrapper const& rhs ) +{ return lhs.dataMember == rhs.dataMember ; } + +typedef unsigned char ArrayOfBytes[256]; + + +// +// A struct that allows testing whether the appropriate copy functions are called. +// +struct CopyFunctionCallTester +{ + bool is_copy_constructed; + bool is_assignment_called; + + CopyFunctionCallTester() + : is_copy_constructed(false), is_assignment_called(false) {} + + CopyFunctionCallTester(const CopyFunctionCallTester & ) + : is_copy_constructed(true), is_assignment_called(false) {} + + CopyFunctionCallTester & operator=(const CopyFunctionCallTester & ) + { + is_assignment_called = true ; + return *this ; + } +}; + + +// +// A struct that allows testing whether its customized swap function is called. +// +struct SwapFunctionCallTester +{ + bool is_custom_swap_called; + int data; + + SwapFunctionCallTester() + : is_custom_swap_called(false), data(0) {} + + SwapFunctionCallTester(const SwapFunctionCallTester & arg) + : is_custom_swap_called(false), data(arg.data) {} + + void swap(SwapFunctionCallTester & arg) + { + std::swap(data, arg.data); + is_custom_swap_called = true; + arg.is_custom_swap_called = true; + } +}; + +void swap(SwapFunctionCallTester & lhs, SwapFunctionCallTester & rhs) +{ + lhs.swap(rhs); +} + + + +template<class T> +void check_initialized_value ( T const& y ) +{ + T initializedValue = boost::initialized_value ; + BOOST_TEST ( y == initializedValue ) ; +} + +#ifdef __BORLANDC__ +#if __BORLANDC__ == 0x582 +void check_initialized_value( NonPOD const& ) +{ + // The initialized_value check is skipped for Borland 5.82 + // and this type (NonPOD), because the following statement + // won't compile on this particular compiler version: + // NonPOD initializedValue = boost::initialized_value() ; + // + // This is caused by a compiler bug, that is fixed with a newer version + // of the Borland compiler. The Release Notes for Delphi(R) 2007 for + // Win32(R) and C++Builder(R) 2007 (http://dn.codegear.com/article/36575) + // say about similar statements: + // both of these statements now compile but under 5.82 got the error: + // Error E2015: Ambiguity between 'V::V(const A &)' and 'V::V(const V &)' +} +#endif +#endif + +// +// This test function tests boost::value_initialized<T> for a specific type T. +// The first argument (y) is assumed have the value of a value-initialized object. +// Returns true on success. +// +template<class T> +bool test ( T const& y, T const& z ) +{ + const int errors_before_test = boost::detail::test_errors(); + + check_initialized_value(y); + + boost::value_initialized<T> x ; + BOOST_TEST ( y == x ) ; + BOOST_TEST ( y == boost::get(x) ) ; + + static_cast<T&>(x) = z ; + boost::get(x) = z ; + BOOST_TEST ( x == z ) ; + + boost::value_initialized<T> const x_c ; + BOOST_TEST ( y == x_c ) ; + BOOST_TEST ( y == boost::get(x_c) ) ; + T& x_c_ref = const_cast<T&>( boost::get(x_c) ) ; + x_c_ref = z ; + BOOST_TEST ( x_c == z ) ; + + boost::value_initialized<T> const copy1 = x; + BOOST_TEST ( boost::get(copy1) == boost::get(x) ) ; + + boost::value_initialized<T> copy2; + copy2 = x; + BOOST_TEST ( boost::get(copy2) == boost::get(x) ) ; + + { + boost::value_initialized<T> * ptr = new boost::value_initialized<T>; + BOOST_TEST ( y == *ptr ) ; + delete ptr; + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + boost::value_initialized<T const> cx ; + BOOST_TEST ( y == cx ) ; + BOOST_TEST ( y == boost::get(cx) ) ; + + boost::value_initialized<T const> const cx_c ; + BOOST_TEST ( y == cx_c ) ; + BOOST_TEST ( y == boost::get(cx_c) ) ; +#endif + + return boost::detail::test_errors() == errors_before_test ; +} + +int main() +{ + BOOST_TEST ( test( 0,1234 ) ) ; + BOOST_TEST ( test( 0.0,12.34 ) ) ; + BOOST_TEST ( test( POD(0,0,0.0), POD('a',1234,56.78f) ) ) ; + BOOST_TEST ( test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ) ; + + NonPOD NonPOD_object( std::string("NonPOD_object") ); + BOOST_TEST ( test<NonPOD *>( 0, &NonPOD_object ) ) ; + + AggregatePODStruct zeroInitializedAggregatePODStruct = { 0.0f, '\0', 0 }; + AggregatePODStruct nonZeroInitializedAggregatePODStruct = { 1.25f, 'a', -1 }; + BOOST_TEST ( test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct) ); + + StringAndInt stringAndInt0; + StringAndInt stringAndInt1; + stringAndInt0.i = 0; + stringAndInt1.i = 1; + stringAndInt1.s = std::string("1"); + BOOST_TEST ( test(stringAndInt0, stringAndInt1) ); + + StructWithDestructor structWithDestructor0; + StructWithDestructor structWithDestructor1; + structWithDestructor0.i = 0; + structWithDestructor1.i = 1; + BOOST_TEST ( test(structWithDestructor0, structWithDestructor1) ); + + StructWithVirtualFunction structWithVirtualFunction0; + StructWithVirtualFunction structWithVirtualFunction1; + structWithVirtualFunction0.i = 0; + structWithVirtualFunction1.i = 1; + BOOST_TEST ( test(structWithVirtualFunction0, structWithVirtualFunction1) ); + + DerivedFromAggregatePODStruct derivedFromAggregatePODStruct0; + DerivedFromAggregatePODStruct derivedFromAggregatePODStruct1; + static_cast<AggregatePODStruct &>(derivedFromAggregatePODStruct0) = zeroInitializedAggregatePODStruct; + static_cast<AggregatePODStruct &>(derivedFromAggregatePODStruct1) = nonZeroInitializedAggregatePODStruct; + BOOST_TEST ( test(derivedFromAggregatePODStruct0, derivedFromAggregatePODStruct1) ); + + AggregatePODStructWrapper aggregatePODStructWrapper0; + AggregatePODStructWrapper aggregatePODStructWrapper1; + aggregatePODStructWrapper0.dataMember = zeroInitializedAggregatePODStruct; + aggregatePODStructWrapper1.dataMember = nonZeroInitializedAggregatePODStruct; + BOOST_TEST ( test(aggregatePODStructWrapper0, aggregatePODStructWrapper1) ); + + ArrayOfBytes zeroInitializedArrayOfBytes = { 0 }; + boost::value_initialized<ArrayOfBytes> valueInitializedArrayOfBytes; + BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0); + + boost::value_initialized<ArrayOfBytes> valueInitializedArrayOfBytes2; + valueInitializedArrayOfBytes2 = valueInitializedArrayOfBytes; + BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0); + + boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester1; + BOOST_TEST ( ! get(copyFunctionCallTester1).is_copy_constructed); + BOOST_TEST ( ! get(copyFunctionCallTester1).is_assignment_called); + + boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester2 = boost::value_initialized<CopyFunctionCallTester>(copyFunctionCallTester1); + BOOST_TEST ( get(copyFunctionCallTester2).is_copy_constructed); + BOOST_TEST ( ! get(copyFunctionCallTester2).is_assignment_called); + + boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester3; + copyFunctionCallTester3 = boost::value_initialized<CopyFunctionCallTester>(copyFunctionCallTester1); + BOOST_TEST ( ! get(copyFunctionCallTester3).is_copy_constructed); + BOOST_TEST ( get(copyFunctionCallTester3).is_assignment_called); + + boost::value_initialized<SwapFunctionCallTester> swapFunctionCallTester1; + boost::value_initialized<SwapFunctionCallTester> swapFunctionCallTester2; + get(swapFunctionCallTester1).data = 1; + get(swapFunctionCallTester2).data = 2; + boost::swap(swapFunctionCallTester1, swapFunctionCallTester2); + BOOST_TEST( get(swapFunctionCallTester1).data == 2 ); + BOOST_TEST( get(swapFunctionCallTester2).data == 1 ); + BOOST_TEST( get(swapFunctionCallTester1).is_custom_swap_called ); + BOOST_TEST( get(swapFunctionCallTester2).is_custom_swap_called ); + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/utility/test/value_init_test_fail1.cpp b/src/boost/libs/utility/test/value_init_test_fail1.cpp new file mode 100644 index 000000000..789e6b334 --- /dev/null +++ b/src/boost/libs/utility/test/value_init_test_fail1.cpp @@ -0,0 +1,27 @@ +// Copyright 2002, Fernando Luis Cacciola Carballal. +// +// 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) +// +// Test program for "boost/utility/value_init.hpp" +// +// Initial: 21 Agu 2002 + +#include <iostream> +#include <string> + +#include "boost/utility/value_init.hpp" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +int main() +{ + boost::value_initialized<int> const x_c ; + + get(x_c) = 1234 ; // this should produce an ERROR + + return 0; +} diff --git a/src/boost/libs/utility/test/value_init_test_fail2.cpp b/src/boost/libs/utility/test/value_init_test_fail2.cpp new file mode 100644 index 000000000..052a2bdff --- /dev/null +++ b/src/boost/libs/utility/test/value_init_test_fail2.cpp @@ -0,0 +1,27 @@ +// Copyright 2002, Fernando Luis Cacciola Carballal. +// +// 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) +// +// Test program for "boost/utility/value_init.hpp" +// +// Initial: 21 Agu 2002 + +#include <iostream> +#include <string> + +#include "boost/utility/value_init.hpp" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +int main() +{ + boost::value_initialized<int const> cx ; + + get(cx) = 1234 ; // this should produce an ERROR + + return 0; +} diff --git a/src/boost/libs/utility/test/value_init_test_fail3.cpp b/src/boost/libs/utility/test/value_init_test_fail3.cpp new file mode 100644 index 000000000..1801f827a --- /dev/null +++ b/src/boost/libs/utility/test/value_init_test_fail3.cpp @@ -0,0 +1,27 @@ +// Copyright 2002, Fernando Luis Cacciola Carballal. +// +// 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) +// +// Test program for "boost/utility/value_init.hpp" +// +// Initial: 21 Agu 2002 + +#include <iostream> +#include <string> + +#include "boost/utility/value_init.hpp" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +int main() +{ + boost::value_initialized<int const> const cx_c ; + + get(cx_c) = 1234 ; // this should produce an ERROR + + return 0; +} diff --git a/src/boost/libs/utility/test/value_init_workaround_test.cpp b/src/boost/libs/utility/test/value_init_workaround_test.cpp new file mode 100644 index 000000000..9ffdffc5d --- /dev/null +++ b/src/boost/libs/utility/test/value_init_workaround_test.cpp @@ -0,0 +1,163 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for the boost::value_initialized<T> workaround. +// +// 17 June 2010 (Created) Niels Dekker + +// Switch the workaround off, before inluding "value_init.hpp". +#define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0 +#include <boost/utility/value_init.hpp> + +#include <iostream> // For cout. +#include <cstdlib> // For EXIT_SUCCESS and EXIT_FAILURE. + +namespace +{ + struct empty_struct + { + }; + + // A POD aggregate struct derived from an empty struct. + // Similar to struct Foo1 from Microsoft Visual C++ bug report 484295, + // "VC++ does not value-initialize members of derived classes without + // user-declared constructor", reported in 2009 by Sylvester Hesp: + // https://connect.microsoft.com/VisualStudio/feedback/details/484295 + struct derived_struct: empty_struct + { + int data; + }; + + bool is_value_initialized(const derived_struct& arg) + { + return arg.data == 0; + } + + + class virtual_destructor_holder + { + public: + int i; + virtual ~virtual_destructor_holder() + { + } + }; + + bool is_value_initialized(const virtual_destructor_holder& arg) + { + return arg.i == 0; + } + + // Equivalent to the Stats class from GCC Bug 33916, + // "Default constructor fails to initialize array members", reported in 2007 by + // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 + // and fixed for GCC 4.2.4. + class private_int_array_pair + { + friend bool is_value_initialized(const private_int_array_pair& arg); + private: + int first[12]; + int second[12]; + }; + + bool is_value_initialized(const private_int_array_pair& arg) + { + for ( unsigned i = 0; i < 12; ++i) + { + if ( (arg.first[i] != 0) || (arg.second[i] != 0) ) + { + return false; + } + } + return true; + } + + struct int_pair_struct + { + int first; + int second; + }; + + typedef int int_pair_struct::*ptr_to_member_type; + + struct ptr_to_member_struct + { + ptr_to_member_type data; + }; + + bool is_value_initialized(const ptr_to_member_struct& arg) + { + return arg.data == 0; + } + + template <typename T> + bool is_value_initialized(const T(& arg)[2]) + { + return + is_value_initialized(arg[0]) && + is_value_initialized(arg[1]); + } + + template <typename T> + bool is_value_initialized(const boost::value_initialized<T>& arg) + { + return is_value_initialized(arg.data()); + } + + // Returns zero when the specified object is value-initializated, and one otherwise. + // Prints a message to standard output if the value-initialization has failed. + template <class T> + unsigned failed_to_value_initialized(const T& object, const char *const object_name) + { + if ( is_value_initialized(object) ) + { + return 0u; + } + else + { + std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl; + return 1u; + } + } + +// A macro that passed both the name and the value of the specified object to +// the function above here. +#define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value) + + // Equivalent to the dirty_stack() function from GCC Bug 33916, + // "Default constructor fails to initialize array members", reported in 2007 by + // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 + void dirty_stack() + { + unsigned char array_on_stack[4096]; + for (unsigned i = 0; i < sizeof(array_on_stack); ++i) + { + array_on_stack[i] = 0x11; + } + } + +} + + +int main() +{ + dirty_stack(); + + // TODO More types may be added later. + const unsigned num_failures = + FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<derived_struct>()) + + FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<virtual_destructor_holder[2]>()) + + FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<private_int_array_pair>()) + + FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<ptr_to_member_struct>()); + +#ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED + // One or more failures are expected. + return num_failures > 0 ? EXIT_SUCCESS : EXIT_FAILURE; +#else + // No failures are expected. + return num_failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +#endif +} diff --git a/src/boost/libs/utility/throw_exception.html b/src/boost/libs/utility/throw_exception.html new file mode 100644 index 000000000..141f48759 --- /dev/null +++ b/src/boost/libs/utility/throw_exception.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv=refresh content="0; URL=../exception/doc/throw_exception.html"> +<title>Automatic redirection</title> +</head> +<body> +Automatic redirection failed, please go to +<a href="../exception/doc/throw_exception.html">throw_exception.html</a>. <hr> +<p>© Copyright Beman Dawes, 2001</p> +<p>Distributed under the Boost Software License, Version 1.0. (See accompanying +file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy +at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p> +</body> +</html> diff --git a/src/boost/libs/utility/utility.htm b/src/boost/libs/utility/utility.htm new file mode 100644 index 000000000..711b58c26 --- /dev/null +++ b/src/boost/libs/utility/utility.htm @@ -0,0 +1,583 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title>Header boost/utility.hpp Documentation</title> + </head> + <body bgcolor="#FFFFFF" text="#000000"> + <h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="center" WIDTH="277" HEIGHT="86">Header + <a href="../../boost/utility.hpp">boost/utility.hpp</a></h1> + <p>The entire contents of the header <code><a href="../../boost/utility.hpp"><boost/utility.hpp></a></code> + are in <code>namespace boost</code>.</p> + <h2>Contents</h2> + <ul> + <li> + Class templates supporting the <a href="doc/html/base_from_member.html"> + base-from-member idiom</a></li> + <li> + Function templates <a href="../core/doc/html/core/checked_delete.html">checked_delete() and + checked_array_delete()</a> (moved to the Boost.Core library)</li> + <li> + Function templates <a href="../iterator/doc/html/iterator/algorithms/next_prior.html">next() and prior()</a> (moved to the Boost.Iterator library)</li> + <li> + Class <a href="../core/doc/html/core/noncopyable.html">noncopyable</a> (moved to the Boost.Core library)</li> + <li> + Function template <a href="../core/doc/html/core/addressof.html">addressof()</a> (moved to the Boost.Core library)</li> + <li>Class template <a href="#result_of">result_of</a></li> + <li> + Macro <a href="#BOOST_BINARY">BOOST_BINARY</a></li> + <li><a href="index.html">Other utilities not part of <code>utility.hpp</code></a></li> + </ul> + <h2> + + <h2><a name="result_of">Class template + result_of</a></h2> <p>The class template + <code>result_of</code> helps determine the type of a + call expression. For example, given an lvalue <code>f</code> of + type <code>F</code> and lvalues <code>t1</code>, + <code>t2</code>, ..., <code>t<em>N</em></code> of + types <code>T1</code>, <code>T2</code>, ..., + <code>T<em>N</em></code>, respectively, the type + <code>result_of<F(T1, T2, ..., + T<em>N</em>)>::type</code> defines the result type + of the expression <code>f(t1, t2, + ...,t<em>N</em>)</code>. This implementation permits + the type <code>F</code> to be a function pointer, + function reference, member function pointer, or class + type. By default, <em>N</em> may be any value between 0 and + 16. To change the upper limit, define the macro + <code>BOOST_RESULT_OF_NUM_ARGS</code> to the maximum + value for <em>N</em>. Class template <code>result_of</code> + resides in the header <code><<a + href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>.</p> + + <p>If your compiler's support for <code>decltype</code> is + adequate, <code>result_of</code> automatically uses it to + deduce the type of the call expression, in which case + <code>result_of<F(T1, T2, ..., + T<em>N</em>)>::type</code> names the type + <code>decltype(boost::declval<F>()(boost::declval<T1>(), + boost::declval<T2>(), ..., + boost::declval<T<em>N</em>>()))</code>, as in the + following example.</p> + + <blockquote> + <pre>struct functor { + template<class T> + T operator()(T x) + { + return x; + } +}; + +typedef boost::result_of< + functor(int) +>::type type; // type is int</pre> + </blockquote> + + <p>You can test whether <code>result_of</code> is using + <code>decltype</code> by checking if the macro + <code>BOOST_RESULT_OF_USE_DECLTYPE</code> is defined after + including <code>result_of.hpp</code>. You can also force + <code>result_of</code> to use <code>decltype</code> by + defining <code>BOOST_RESULT_OF_USE_DECLTYPE</code> prior + to including <code>result_of.hpp</code>.</p> + + <p>If <code>decltype</code> is not used, + then automatic result type deduction of function + objects is not possible. Instead, <code>result_of</code> + uses the following protocol to allow the programmer to + specify a type. When <code>F</code> is a class type with a + member type <code>result_type</code>, + <code>result_of<F(T1, T2, ..., + T<em>N</em>)>::type</code> is + <code>F::result_type</code>. When <code>F</code> does + not contain <code>result_type</code>, + <code>result_of<F(T1, T2, ..., + T<em>N</em>)>::type</code> is <code>F::result<F(T1, + T2, ..., T<em>N</em>)>::type</code> when + <code><em>N</em> > 0</code> or <code>void</code> + when <code><em>N</em> = 0</code>. 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.</p> + + <blockquote> + <pre>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</pre> + </blockquote> + + <p>Since <code>decltype</code> is a new language + feature recently standardized in C++11, + if you are writing a function object + to be used with <code>result_of</code>, for + maximum portability, you might consider following + the above protocol even if your compiler has + proper <code>decltype</code> support. If you wish to continue to + use the protocol on compilers that + support <code>decltype</code>, there are two options: + You can use <code>boost::tr1_result_of</code>, which is also + defined in <code><<a href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>. + Alternatively, you can define the macro + <code>BOOST_RESULT_OF_USE_TR1</code>, which causes + <code>result_of</code> to use the protocol described + above instead of <code>decltype</code>. If you choose to + follow the protocol, take care to ensure that the + <code>result_type</code> and + <code>result<></code> members accurately + represent the return type of + <code>operator()</code> given a call expression.</p> + + <p>Additionally, <code>boost::result_of</code> + provides a third mode of operation, which some users + may find convenient. When + <code>BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK</code> + is defined, <code>boost::result_of</code> behaves as + follows. If the function object has a member + type <code>result_type</code> or member + template <code>result<></code>, then + <code>boost::result_of</code> will use the TR1 + protocol. Otherwise, + <code>boost::result_of</code> will + use <code>decltype</code>. Using TR1 with + a <code>declytpe</code> fallback may workaround + certain problems at the cost of portability. For + example: + <ul> + <li>Deficient compiler: If your code + requires <code>boost::result_of</code> to work + with incomplete return types but your + compiler's <code>decltype</code> 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 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf">N3276</a>) + and is not implemented by some compilers.</li> + + <li>Deficient legacy code: If your existing TR1 + function object advertises a different type than + the actual result type deduced + by <code>decltype</code>, then using TR1 with a + <code>decltype</code> 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 <a href="#result_of_tr1_diff">differences</a> + between <code>boost::result_of</code> and TR1.</li> + </ul> + + <a name="BOOST_NO_RESULT_OF"></a> + <p>This implementation of <code>result_of</code> + requires class template partial specialization, the + ability to parse function types properly, and support + for SFINAE. If <code>result_of</code> is not supported + by your compiler, including the header + <code>boost/utility/result_of.hpp</code> will + define the macro <code>BOOST_NO_RESULT_OF</code>.</p> + + <p>For additional information + about <code>result_of</code>, see the C++ Library + Technical Report, + <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>, + or, for motivation and design rationale, + the <code>result_of</code> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</p> + + <a name="result_of_guidelines"> + <h3>Usage guidelines for boost::result_of</h3> + </a> + + <p>The following are general suggestions about when + and how to use <code>boost::result_of</code>.</p> + + <ol> + <li> If you are targeting C++11 and are not concerned + about portability to non-compliant compilers or + previous versions of the standard, then use + <code>std::result_of</code>. If <code>std::result_of</code> + meets your needs, then there's no reason to stop using + it.</li> + + <li> If you are targeting C++11 but may port your code + to legacy compilers at some time in the future, then + use <code>boost::result_of</code> with + <code>decltype</code>. When <code>decltype</code> is + used <code>boost::result_of</code> + and <code>std::result_of</code> are usually + interchangeable. See the documentation on + known <a href="#result_of_cxx11_diff">differences</a> + between boost::result_of and C++11 result_of.</li> + + <li> If compiler portability is required, + use <code>boost::result_of</code> with the TR1 protocol.</li> + </ol> + + <p>Regardless of how you + configure <code>boost::result_of</code>, 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. <code>boost::result_of</code> must be passed + the appropriately cv-qualified types in order to + deduce the corresponding return type. For example: + + <blockquote> + <pre>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 &</pre> + </blockquote> + + <a name="result_of_tr1_protocol_guidelines"> + <h3>Usage guidelines for the TR1 result_of protocol</h3> + </a> + + <p>On compliant C++11 + compilers, <code>boost::result_of</code> can + use <code>decltype</code> 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.</p> + + <ul> + <li>When the return type does not depend on the + argument types or the cv-qualification of the + function object, simply + define <code>result_type</code>. There is no need + to use the <code>result</code> template unless the + return type varies.</li> + + <li>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: + + <blockquote> + <pre>struct functor { + typedef int result_type; + result_type operator()(int); +};</pre> + </blockquote> </li> + + <li>Always specify the <code>result</code> + specialization near the corresponding + <code>operator()</code> overload. This can make it + easier to keep the specializations in sync with the + overloads. For example: + + <blockquote> + <pre>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; +};</pre> + </blockquote> </li> + + <li>Use type transformations to simplify + the <code>result</code> template specialization. For + example, the following uses + <a href="../type_traits/doc/html/index.html">Boost.TypeTraits</a> + to specialize the <code>result</code> template for + a single <code>operator()</code> that can be called on + both a const and non-const function object with + either an lvalue or rvalue argument. + + <blockquote> + <pre>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; +};</pre> + </blockquote></li> + </ul> + + <a name="result_of_tr1_diff"> + <h3>Known differences between boost::result_of and TR1 result_of</h3> + </a> + + When using <code>decltype</code>, <code>boost::result_of</code> + ignores the TR1 protocol and instead deduces the + return type of function objects directly + via <code>decltype</code>. 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 <code>boost::result_of</code> is known to differ depending on + whether <code>decltype</code> or the TR1 protocol is + used. + + <ul> + <li> TR1 protocol misusage + + <p>When using the TR1 + protocol, <code>boost::result_of</code> 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 <code>decltype</code>, these subtle bugs + may result in compilation errors. For example:</p> + + <blockquote> + <pre>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</pre> + </blockquote> + + <p>Note that the user can + force <code>boost::result_of</code> to use the TR1 + protocol even on platforms that + support <code>decltype</code> by + defining <code>BOOST_RESULT_OF_USE_TR1</code>.</p></li> + + <li> Nullary function objects + + <p>When using the TR1 protocol, <code>boost::result_of</code> + cannot always deduce the type of calls to + nullary function objects, in which case the + type defaults to void. When using <code>decltype</code>, + <code>boost::result_of</code> always gives the actual type of the + call expression. For example:</p> + + <blockquote> + <pre>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</pre> + </blockquote> + + <p>Note that there are some workarounds for the + nullary function problem. So long as the return + type does not vary, + <code>result_type</code> can always be used to + specify the return type regardless of arity. If the + return type does vary, then the user can + specialize <code>boost::result_of</code> itself for + nullary calls.</p></li> + + <li> Non-class prvalues and cv-qualification + + <p>When using the TR1 + protocol, <code>boost::result_of</code> will + report the cv-qualified type specified + by <code>result_type</code> or + the <code>result</code> template regardless of + the actual cv-qualification of the call + expression. When using + <code>decltype</code>, <code>boost::result_of</code> + will report the actual type of the call expression, + which is not cv-qualified when the expression is a + non-class prvalue. For example:</p> + + <blockquote> + <pre>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</pre> + </blockquote></li> + </ul> + + <a name="result_of_cxx11_diff"> + <h3>Known differences between boost::result_of and C++11 result_of</h3> + </a> + + <p>When using <code>decltype</code>, <code>boost::result_of</code> + implements most of the C++11 result_of + specification. One known exception is that + <code>boost::result_of</code> does not implement the + requirements regarding pointers to member data.</p> + + <p>Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others</p> + + <h2><a name="BOOST_BINARY">Macro BOOST_BINARY</a></h2> + + <p>The macro <code>BOOST_BINARY</code> 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 (<i>2.13.1p1</i>). 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.</p> + + <p>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.</p> + + + <p>The BOOST_BINARY family of macros resides in the header + <a + href="../../boost/utility/binary.hpp"><boost/utility/binary.hpp></a> + which is automatically included by + <a + href="../../boost/utility.hpp"><boost/utility.hpp></a>. + + <p>Contributed by Matt Calabrese.</p><p> + </p><h3>Example</h3> + <blockquote> + <pre> +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 +} +</pre></blockquote> + <hr> + <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan +-->04 September, 2008<!--webbot bot="Timestamp" endspan i-checksum="39369" +--> + </p> + <p>© Copyright Beman Dawes 1999-2003.</p> +<p>Distributed under the Boost Software License, Version 1.0. See +<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p> + + </body> +</html> diff --git a/src/boost/libs/utility/value_init.htm b/src/boost/libs/utility/value_init.htm new file mode 100644 index 000000000..3222f691c --- /dev/null +++ b/src/boost/libs/utility/value_init.htm @@ -0,0 +1,514 @@ +<html> +<head> + + <meta http-equiv="Content-Type" + content="text/html; charset=iso-8859-1"> + <title>value_initialized</title> + +</head> + <body vlink="#800080" link="#0000ff" text="#000000" bgcolor="#ffffff"> + +<h2><img src="../../boost.png" width="276" height="86"> + Header <<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>> + </h2> + +<h2>Contents</h2> + +<dl> + <dt><a href="#rationale">Rationale</a></dt> + <dt><a href="#intro">Introduction</a></dt> + <dt><a href="#details">Details</a></dt> +</dl> + +<ul> + <li><a href="#valueinit">value-initialization</a></li> + <li><a href="#valueinitsyn">value-initialization syntax</a></li> + <li><a href="#compiler_issues">compiler issues</a></li> + +</ul> + +<dl class="page-index"> + <dt><a href="#types">Types and objects</a></dt> +</dl> + +<ul> + <li><a href="#val_init"><code>template class value_initialized<T></code></a></li> + <li><a href="#initialized"><code>template class initialized<T></code></a></li> + <li><a href="#initialized_value"><code>initialized_value</code></a></li> + +</ul> + <a href="#acknowledgements">Acknowledgements</a><br> + <br> + +<hr> +<h2><a name="rationale"></a>Rationale</h2> + +<p>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 <code>value_initialized</code> provides +a solution with consistent syntax for value initialization of scalar, +union and class types. +Moreover, <code>value_initialized</code> offers a workaround to various +compiler issues regarding value-initialization. + +Furthermore, a <code>const</code> object, <code>initialized_value</code> is provided, +to avoid repeating the type name when retrieving the value from a +<code>value_initialized<T></code> object. +<br> + </p> + +<h2><a name="intro"></a>Introduction</h2> + +<p> +There are various ways to initialize a variable, in C++. The following +declarations all <em>may</em> have a local variable initialized to its default +value: +<pre> + T1 var1; + T2 var2 = 0; + T3 var3 = {}; + T4 var4 = T4(); +</pre> +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 <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"> +DefaultConstructible</a> 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 <code>var1</code> is <em>indeterminate</em> when +its type is an arithmetic type, like <code>int</code>, <code>float</code>, or <code>char</code>. +An arithmetic variable +is of course initialized properly by the second declaration, <code>T2 +var2 = 0</code>. 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, <code>T3 var3 = {}</code> +initializes an aggregate, typically a "C-style" <code>struct</code> 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 [<a href="#references">1</a>]!) +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, <code>T4 var4 = T4()</code>, should be read +as follows: First a temporary object is created, by <code>T4()</code>. +This object is <a href="#valueinit">value-initialized</a>. Next the temporary +object is copied to the named variable, <code>var4</code>. Afterwards, the temporary +is destroyed. While the copying and the destruction are likely to +be optimized away, C++ still requires the type <code>T4</code> to be +<a href="CopyConstructible.html">CopyConstructible</a>. +(So <code>T4</code> needs to be <em>both</em> DefaultConstructible <em>and</em> 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 <a href="utility.htm#Class_noncopyable">boost::noncopyable</a>. +Scott Meyers [<a href="#references">2</a>] explains why a class would be defined like that. +</p> +<p> +There is another, less obvious disadvantage to the fourth form, <code>T4 var4 = T4()</code>: +It suffers from various <a href="#compiler_issues">compiler issues</a>, causing +a variable to be left uninitialized in some compiler specific cases. +</p> +<p> +The template <a href="#val_init"><code>value_initialized</code></a> +offers a generic way to initialize +an object, like <code>T4 var4 = T4()</code>, 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 <em>only</em> requires the type to be DefaultConstructible. +A properly <em>value-initialized</em> object of type <code>T</code> is +constructed by the following declaration: +<pre> + value_initialized<T> var; +</pre> +</p> +<p> +The template <a href="#initialized"><code>initialized</code></a> +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. +</p> +<p> +The <code>const</code> object <a href="#initialized_value"><code>initialized_value</code></a> +allows value-initializing a variable as follows: +<pre> + T var = initialized_value ; +</pre> +This form of initialization is semantically equivalent to <code>T4 var4 = T4()</code>, +but robust against the aforementioned compiler issues. + +</p> + +<h2><a name="details"></a>Details</h2> +<p>The C++ standard [<a href="#references">3</a>] contains the definitions + of <code>zero-initialization</code> and <code>default-initialization</code>. + Informally, zero-initialization means that the object is given the initial + value 0 (converted to the type) and default-initialization means that + POD [<a href="#references">4</a>] types are zero-initialized, while non-POD class + types are initialized with their corresponding default constructors. A +<i>declaration</i> can contain an <i>initializer</i>, 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 <i>declaration</i> + has no <i>initializer</i> and it is of a non-<code>const</code>, non-<code>static</code> + POD type, the initial value is indeterminate: <cite>(see §8.5, [dcl.init], for the + accurate definitions).</cite></p> + +<pre>int x ; // no initializer. x value is indeterminate.<br>std::string s ; // no initializer, s is default-constructed.<br><br>int y = int() ; <br>// y is initialized using copy-initialization<br>// but the temporary uses an empty set of parentheses as the initializer,<br>// so it is default-constructed.<br>// A default constructed POD type is zero-initialized,<br>// therefore, y == 0.<br><br>void foo ( std::string ) ;<br>foo ( std::string() ) ; <br>// the temporary string is default constructed <br>// as indicated by the initializer () </pre> + +<h3><a name="valueinit">value-initialization</a></h3> + +<p>The first <a + href="http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html">Technical + Corrigendum for the C++ Standard</a> (TC1), whose draft was released to + the public in November 2001, introduced <a + href="http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core + Issue 178</a> (among many other issues, of course).</p> + +<p> That issue introduced the new concept of <code>value-initialization</code> + (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).</p> + +<p>In order to specify value-initialization of an object we need to use the + empty-set initializer: (). </p> + +<p>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. </p> + +<pre>template<class T> void eat(T);<br>int x ; // indeterminate initial value.<br>std::string s; // default-initialized.<br>eat ( int() ) ; // value-initialized<br>eat ( std::string() ) ; // value-initialized</pre> + +<h4><a name="valueinitsyn">value-initialization</a> syntax</h4> + +<p>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: </p> + +<pre>int x() ; // declares function int(*)()</pre> + +<p>Thus, the empty () must be put in some other initialization context.</p> + +<p>One alternative is to use copy-initialization syntax:</p> + +<pre>int x = int() ;</pre> + +<p>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.</p> + +<p>One possible generic solution is to use value-initialization of a non static +data member:</p> + +<pre>template<class T> <br>struct W <br>{<br> // value-initialization of 'data' here.<br> W() : data() {}<br> T data ;<br>} ;<br>W<int> w ;<br>// w.data is value-initialized for any type. </pre> + +<p>This is the solution as it was supplied by earlier versions of the +<code>value_initialized<T></code> template + class. Unfortunately this approach suffered from various compiler issues.</p> + +<h4><a name="compiler_issues">compiler issues</a> </h4> + +Various compilers haven't yet fully implemented value-initialization. +So when an object should be <em>value-initialized</em> (according to the C++ Standard), +it <em>may</em> 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 <em>aggregates</em> uninitialized, when they +should be value-initialized. Value-initialization of objects of a pointer-to-member type may also +go wrong on various compilers. +</p> +<p> +At the moment of writing, May 2010, the following reported issues regarding +value-initialization are still there in current compiler releases: +<ul> +<li> +<a href="https://connect.microsoft.com/VisualStudio/feedback/details/100744"> +Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression</a> +<br>Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005 +</li><li> +<a href="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</a> +<br>Reported by Sylvester Hesp, 2009 +</li><li> +<a href="https://connect.microsoft.com/VisualStudio/feedback/details/499606"> +Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization</a> +<br>Reported by Alex Vakulenko, 2009 +</li><li> +<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=83751"> +Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized</a> +<br>Reported by Niels Dekker (LKEB), 2010 +</li><li> +<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=83851"> +Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798</a> +<br>Reported by Niels Dekker, 2010 +</li><li> +<a href="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()"</a> +<br>Reported by Niels Dekker, 2010 +</li><li> +Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate. +<br>Reported to Steve Clamage by Niels Dekker, 2010 +</li><li> +IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate. +<br>Reported to Michael Wong by Niels Dekker, 2010 +</li><li> +Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error +on Intel 11.1. +<br>Reported by John Maddock, 2010 +</li> +</ul> +Note that all known GCC issues regarding value-initialization are +fixed with GCC version 4.4, including +<a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111">GCC Bug 30111</a>. +Clang also has completely implemented value-initialization, as far as we know, +now that <a href="http://llvm.org/bugs/show_bug.cgi?id=7139">Clang Bug 7139</a> is fixed. +</p><p> + +New versions of <code>value_initialized</code> +(Boost release version 1.35 or higher) +offer a workaround to these issues: <code>value_initialized</code> 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 +<a href="../config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects" +>compiler defect macro</a> BOOST_NO_COMPLETE_VALUE_INITIALIZATION. +</p> + +<h2><a name="types"></a>Types and objects</h2> + +<h2><a name="val_init"><code>template class value_initialized<T></code></a></h2> + +<pre>namespace boost {<br><br>template<class T><br>class value_initialized<br>{ +<br> public : +<br> value_initialized() : x() {} +<br> operator T const &() const { return x ; } +<br> operator T&() { return x ; } +<br> T const &data() const { return x ; } +<br> T& data() { return x ; } +<br> void swap( value_initialized& ); +<br> +<br> private : +<br> <i>unspecified</i> x ; +<br>} ; +<br> +<br>template<class T> +<br>T const& get ( value_initialized<T> const& x ) +<br>{ +<br> return x.data() ; +<br>} +<br> +<br>template<class T> +<br>T& get ( value_initialized<T>& x ) +<br>{ +<br> return x.data() ; +<br>} +<br> +<br>template<class T> +<br>void swap ( value_initialized<T>& lhs, value_initialized<T>& rhs ) +<br>{ +<br> lhs.swap(rhs) ; +<br>} +<br> +<br>} // namespace boost +<br></pre> + +<p>An object of this template class is a <code>T</code>-wrapper convertible + to <code>'T&'</code> whose wrapped object (data member of type <code>T</code>) + is <a href="#valueinit">value-initialized</a> upon default-initialization + of this wrapper class: </p> + +<pre>int zero = 0 ;<br>value_initialized<int> x ;<br>assert ( x == zero ) ;<br><br>std::string def ;<br>value_initialized< std::string > y ;<br>assert ( y == def ) ;<br></pre> + +<p>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 <a + href="#valueinitsyn">value-initialization syntax</a>)</p> + +<p>The wrapped object can be accessed either through the conversion operator + <code>T&</code>, the member function <code>data()</code>, or the +non-member function <code>get()</code>: </p> + +<pre>void watch(int);<br>value_initialized<int> x; +<br><br>watch(x) ; // operator T& used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre> + +<p>Both <code>const</code> and non-<code>const</code> objects can be wrapped. + Mutable objects can be modified directly from within the wrapper but constant + objects cannot:</p> + +<p>When <code>T</code> is a <em>Swappable</em> type, <code>value_initialized<T></code> + is swappable as well, by calling its <code>swap</code> member function + as well as by calling <code>boost::swap</code>.</p> + +<pre>value_initialized<int> x ; <br>static_cast<int&>(x) = 1 ; // OK<br>get(x) = 1 ; // OK +<br><br>value_initialized<int const> y ; <br>static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&<br>static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value<br>get(y) = 1 ; // ERROR: cannot modify a const value</pre> + +<h3>Warning:</h3> + +<p>The <code>value_initialized</code> implementation of Boost version 1.40.0 and older +allowed <i>non-const</i> access to the wrapped object, from a constant wrapper, +both by its conversion operator and its <code>data()</code> member function. For example:</p> + +<pre>value_initialized<int> const x_c ;<br>int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const. +<br>xr = 2 ; </pre> + +<p>The reason for this obscure behavior was that some compilers + didn't accept the following valid code:</p> + +<pre>struct X<br>{<br> operator int&() ;<br> operator int const&() const ; <br>};<br>X x ;<br>(x == 1 ) ; // ERROR HERE!</pre> + +<p>The current version of <code>value_initialized</code> no longer has this obscure behavior. +As compilers nowadays widely support overloading the conversion operator by having a <code>const</code> and a <code>non-const</code> version, we have decided to fix the issue accordingly. So the current version supports the idea of logical constness. +<br> + </p> + +<h3>Recommended practice: The non-member get() idiom</h3> + +<p>The obscure behavior of being able to modify a non-<code>const</code> +wrapped object from within a constant wrapper (as was supported by previous +versions of <code>value_initialized</code>) +can be avoided if access to +the wrapped object is always performed with the <code>get()</code> idiom:</p> + +<pre>value_initialized<int> x ;<br>get(x) = 1 ; // OK<br><br>value_initialized<int const> cx ;<br>get(x) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int> const x_c ;<br>get(x_c) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int const> const cx_c ;<br>get(cx_c) = 1 ; // ERROR: Cannot modify a const object<br></pre> + +<h2><a name="initialized"><code>template class initialized<T></code></a></h2> + +<pre>namespace boost {<br><br>template<class T><br>class initialized<br>{ +<br> public : +<br> initialized() : x() {} +<br> explicit initialized(T const & arg) : x(arg) {} +<br> operator T const &() const; +<br> operator T&(); +<br> T const &data() const; +<br> T& data(); +<br> void swap( initialized& ); +<br> +<br> private : +<br> <i>unspecified</i> x ; +<br>} ; +<br> +<br>template<class T> +<br>T const& get ( initialized<T> const& x ); +<br> +<br>template<class T> +<br>T& get ( initialized<T>& x ); +<br> +<br>template<class T> +<br>void swap ( initialized<T>& lhs, initialized<T>& rhs ); +<br> +<br>} // namespace boost +<br></pre> + +The template class <code>boost::initialized<T></code> supports both value-initialization +and direct-initialization, so its interface is a superset of the interface +of <code>value_initialized<T></code>: Its default-constructor +value-initializes the wrapped object just like the default-constructor of +<code>value_initialized<T></code>, but <code>boost::initialized<T></code> +also offers an extra <code>explicit</code> +constructor, which direct-initializes the wrapped object by the specified value. +<p> + +<code>initialized<T></code> is especially useful when the wrapped +object must be either value-initialized or direct-initialized, depending on +runtime conditions. For example, <code>initialized<T></code> 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 <i>always</i> be value-initialized, <code>value_initialized<T></code> +may be preferable. And if the object must always be +direct-initialized, none of the two wrappers really needs to be used. +</p> + + +<h2><a name="initialized_value"><code>initialized_value</code></a></h2> + +<pre> +namespace boost { +class initialized_value_t +{ + public : + template <class T> operator T() const ; +}; + +initialized_value_t const initialized_value = {} ; + +} // namespace boost +</pre> + +<code>initialized_value</code> provides a convenient way to get +an initialized value: its conversion operator provides an appropriate +<em>value-initialized</em> object for any CopyConstructible type. + +Suppose you need to have an initialized variable of type <code>T</code>. +You could do it as follows: +<pre> + T var = T(); +</pre> +But as mentioned before, this form suffers from various compiler issues. +The template <code>value_initialized</code> offers a workaround: +<pre> + T var = get( value_initialized<T>() ); +</pre> +Unfortunately both forms repeat the type name, which +is rather short now (<code>T</code>), but could of course be +more like <code>Namespace::Template<Arg>::Type</code>. +Instead, one could use <code>initialized_value</code> as follows: +<pre> + T var = initialized_value ; +</pre> + +<h3><a name="references">References</a></h3> + [1] Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote + various papers, proposing to extend the support for brace-enclosed <em>initializer lists</em> + in the next version of C++. + This would allow a variable <code>var</code> of any DefaultConstructible type + <code>T</code> to be <em>value-initialized</em> by doing <code>T var = {}</code>. + The papers are listed at Bjarne's web page, + <a href="http://www.research.att.com/~bs/WG21.html">My C++ Standards committee papers</a> <br> + [2] Scott Meyers, Effective C++, Third Edition, item 6, + <em>Explicitly disallow the use of compiler-generated functions you do not want</em>, + <a href="http://www.aristeia.com/books.html">Scott Meyers: Books and CDs</a> <br> + [3] The C++ Standard, Second edition (2003), ISO/IEC 14882:2003 <br> + [4] POD stands for "Plain Old Data" + +<h3><a name="acknowledgements"></a>Acknowledgements</h3> + value_initialized was developed by Fernando Cacciola, with help and +suggestions from David Abrahams and Darin Adler.<br> +Special thanks to Björn Karlsson who carefully edited and completed this documentation. + +<p>value_initialized was reimplemented by Fernando Cacciola and Niels Dekker +for Boost release version 1.35 (2008), offering a workaround to various compiler issues. + </p> +<p><code>boost::initialized</code> was very much inspired by feedback from Edward Diener and + Jeffrey Hellrung. + </p> +<p>initialized_value was written by Niels Dekker, and added to Boost release version 1.36 (2008). + </p> +<p>Developed by <a href="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</a>, + the latest version of this file can be found at <a + href="http://www.boost.org">www.boost.org</a>. + </p> + +<hr> +<p>Revised 30 May 2010</p> + +<p>© Copyright Fernando Cacciola, 2002 - 2010.</p> + +<p>Distributed under the Boost Software License, Version 1.0. See +<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p> + + <br> + <br> + +</body> +</html> |