| [/ |
| 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 proxying 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 proxying iterators |
| then takes special care over the swap to ensure that the algorithm |
| works correctly for both proxying iterators, and even iterators of |
| different types |
| (see [@../../examples/iter_swap_example.cpp iter_swap_example.cpp]): |
| |
| // |
| // iter_swap: |
| // tests whether iterator is a proxying 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, T 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] |
| |