Squashed 'third_party/boostorg/type_traits/' content from commit 059ed88
Change-Id: I222c604dfa1db194bf53bc6aa1152fb16e83ce06
git-subtree-dir: third_party/boostorg/type_traits
git-subtree-split: 059ed8839da3fecd1e8b62cdc11be006f6346b5e
diff --git a/doc/examples.qbk b/doc/examples.qbk
new file mode 100644
index 0000000..489b91e
--- /dev/null
+++ b/doc/examples.qbk
@@ -0,0 +1,237 @@
+[/
+ Copyright 2007 John Maddock.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+]
+
+[section:examples Examples]
+
+[section:copy An Optimized Version of std::copy]
+
+Demonstrates a version of `std::copy` that uses `__has_trivial_assign` to
+determine whether to use `memcpy` to optimise the copy operation
+(see [@../../examples/copy_example.cpp copy_example.cpp]):
+
+ //
+ // opt::copy
+ // same semantics as std::copy
+ // calls memcpy where appropriate.
+ //
+
+ namespace detail{
+
+ template<typename I1, typename I2, bool b>
+ I2 copy_imp(I1 first, I1 last, I2 out, const boost::__integral_constant<bool, b>&)
+ {
+ while(first != last)
+ {
+ *out = *first;
+ ++out;
+ ++first;
+ }
+ return out;
+ }
+
+ template<typename T>
+ T* copy_imp(const T* first, const T* last, T* out, const boost::__true_type&)
+ {
+ memmove(out, first, (last-first)*sizeof(T));
+ return out+(last-first);
+ }
+
+
+ }
+
+ template<typename I1, typename I2>
+ inline I2 copy(I1 first, I1 last, I2 out)
+ {
+ //
+ // We can copy with memcpy if T has a trivial assignment operator,
+ // and if the iterator arguments are actually pointers (this last
+ // requirement we detect with overload resolution):
+ //
+ typedef typename std::iterator_traits<I1>::value_type value_type;
+ return detail::copy_imp(first, last, out, boost::__has_trivial_assign<value_type>());
+ }
+
+
+[endsect]
+
+[section:fill An Optimised Version of std::fill]
+
+Demonstrates a version of `std::fill` that uses `__has_trivial_assign` to
+determine whether to use `memset` to optimise the fill operation
+(see [@../../examples/fill_example.cpp fill_example.cpp]):
+
+ //
+ // fill
+ // same as std::fill, but uses memset where appropriate
+ //
+ namespace detail{
+
+ template <typename I, typename T, bool b>
+ void do_fill(I first, I last, const T& val, const boost::__integral_constant<bool, b>&)
+ {
+ while(first != last)
+ {
+ *first = val;
+ ++first;
+ }
+ }
+
+ template <typename T>
+ void do_fill(T* first, T* last, const T& val, const boost::__true_type&)
+ {
+ std::memset(first, val, last-first);
+ }
+
+ }
+
+ template <class I, class T>
+ inline void fill(I first, I last, const T& val)
+ {
+ //
+ // We can do an optimised fill if T has a trivial assignment
+ // operator and if it's size is one:
+ //
+ typedef boost::__integral_constant<bool,
+ ::boost::__has_trivial_assign<T>::value && (sizeof(T) == 1)> truth_type;
+ detail::do_fill(first, last, val, truth_type());
+ }
+
+
+[endsect]
+
+[section:destruct An Example that Omits Destructor Calls For Types with Trivial Destructors]
+
+Demonstrates a simple algorithm that uses `__has_trivial_destruct` to
+determine whether to destructors need to be called
+(see [@../../examples/trivial_destructor_example.cpp trivial_destructor_example.cpp]):
+
+ //
+ // algorithm destroy_array:
+ // The reverse of std::unitialized_copy, takes a block of
+ // initialized memory and calls destructors on all objects therein.
+ //
+
+ namespace detail{
+
+ template <class T>
+ void do_destroy_array(T* first, T* last, const boost::__false_type&)
+ {
+ while(first != last)
+ {
+ first->~T();
+ ++first;
+ }
+ }
+
+ template <class T>
+ inline void do_destroy_array(T* first, T* last, const boost::__true_type&)
+ {
+ }
+
+ } // namespace detail
+
+ template <class T>
+ inline void destroy_array(T* p1, T* p2)
+ {
+ detail::do_destroy_array(p1, p2, ::boost::__has_trivial_destructor<T>());
+ }
+
+
+[endsect]
+
+[section:iter An improved Version of std::iter_swap]
+
+Demonstrates a version of `std::iter_swap` that use type traits to
+determine whether an it's arguments are proxy iterators or not,
+if they're not then it just does a `std::swap` of it's dereferenced
+arguments (the
+same as `std::iter_swap` does), however if they are proxy iterators
+then takes special care over the swap to ensure that the algorithm
+works correctly for both proxy iterators, and even iterators of
+different types
+(see [@../../examples/iter_swap_example.cpp iter_swap_example.cpp]):
+
+ //
+ // iter_swap:
+ // tests whether iterator is a proxy iterator or not, and
+ // uses optimal form accordingly:
+ //
+ namespace detail{
+
+ template <typename I>
+ static void do_swap(I one, I two, const boost::__false_type&)
+ {
+ typedef typename std::iterator_traits<I>::value_type v_t;
+ v_t v = *one;
+ *one = *two;
+ *two = v;
+ }
+ template <typename I>
+ static void do_swap(I one, I two, const boost::__true_type&)
+ {
+ using std::swap;
+ swap(*one, *two);
+ }
+
+ }
+
+ template <typename I1, typename I2>
+ inline void iter_swap(I1 one, I2 two)
+ {
+ //
+ // See is both arguments are non-proxying iterators,
+ // and if both iterator the same type:
+ //
+ typedef typename std::iterator_traits<I1>::reference r1_t;
+ typedef typename std::iterator_traits<I2>::reference r2_t;
+
+ typedef boost::__integral_constant<bool,
+ ::boost::__is_reference<r1_t>::value
+ && ::boost::__is_reference<r2_t>::value
+ && ::boost::__is_same<r1_t, r2_t>::value> truth_type;
+
+ detail::do_swap(one, two, truth_type());
+ }
+
+
+[endsect]
+
+[section:to_double Convert Numeric Types and Enums to double]
+
+Demonstrates a conversion of
+[@../../../../libs/numeric/conversion/doc/html/boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types
+Numeric Types]
+and enum types to double:
+
+ template<class T>
+ inline double to_double(T const& value)
+ {
+ typedef typename boost::promote<T>::type promoted;
+ return boost::numeric::converter<double,promoted>::convert(value);
+ }
+
+[endsect]
+
+[section:improved_min Improving std::min with common_type]
+
+An improved `std::min` function could be written like this:
+
+ template <class T, class U>
+ typename __common_type<T, U>::type min(T t, U u)
+ {
+ return t < u ? t : u;
+ }
+
+And now expressions such as:
+
+ min(1, 2.0)
+
+will actually compile and return the correct type!
+
+[endsect]
+[endsect]
+