diff --git a/doc/type_traits.qbk b/doc/type_traits.qbk index d4c1420..32733ee 100644 --- a/doc/type_traits.qbk +++ b/doc/type_traits.qbk @@ -10,6 +10,7 @@ http://www.boost.org/LICENSE_1_0.txt ) ] + [authors [authors, various]] [category template] [category generic] [last-revision $Date$] diff --git a/examples/copy_example.cpp b/examples/copy_example.cpp index 12c6e51..d90cec0 100644 --- a/examples/copy_example.cpp +++ b/examples/copy_example.cpp @@ -1,7 +1,7 @@ /* * - * (C) Copyright John Maddock 1999. + * (C) Copyright John Maddock 1999-2005. * 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) @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -36,8 +37,8 @@ namespace opt{ namespace detail{ -template -I2 copy_imp(I1 first, I1 last, I2 out) +template +I2 copy_imp(I1 first, I1 last, I2 out, const boost::integral_constant&) { while(first != last) { @@ -48,79 +49,28 @@ I2 copy_imp(I1 first, I1 last, I2 out) return out; } -template -struct copier -{ - template - static I2 do_copy(I1 first, I1 last, I2 out) - { return copy_imp(first, last, out); } -}; - -template <> -struct copier -{ - template - static I2* do_copy(I1* first, I1* last, I2* out) - { - memcpy(out, first, (last-first)*sizeof(I2)); - return out+(last-first); - } -}; - - -} - -#ifndef BOOST_NO_STD_ITERATOR_TRAITS - -template -inline I2 copy(I1 first, I1 last, I2 out) -{ - typedef typename boost::remove_cv::value_type>::type v1_t; - typedef typename boost::remove_cv::value_type>::type v2_t; - return detail::copier< - ::boost::type_traits::ice_and< - ::boost::is_same::value, - ::boost::is_pointer::value, - ::boost::is_pointer::value, - ::boost::has_trivial_assign::value - >::value>::do_copy(first, last, out); -} - -#else // BOOST_NO_STD_ITERATOR_TRAITS - -// -// If there is no standard iterator_traits then we have to -// use overloading rather than iterator_traits to detect -// when we have T*'s to copy. Note that we cannot overload -// copy directly as that will cause some standard conforming -// code to fail to build: - -namespace detail{ - -template -inline I2 copy_(const I1& first, const I1& last, const I2& out) -{ - return detail::copier::do_copy(first, last, out); -} - template -inline T* copy_(const T*& first, const T*& last, T*& out) +T* copy_imp(const T* first, const T* last, T* out, const boost::true_type&) { - return detail::copier< - ::boost::has_trivial_assign::value - >::do_copy(first, last, out); + memcpy(out, first, (last-first)*sizeof(T)); + return out+(last-first); } -} // namespace detail + +} template inline I2 copy(I1 first, I1 last, I2 out) { - return detail::copy_(first, last, 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::value_type value_type; + return detail::copy_imp(first, last, out, boost::has_trivial_assign()); } -#endif // BOOST_NO_STD_ITERATOR_TRAITS - }; // namespace opt // @@ -176,18 +126,6 @@ int cpp_main(int argc, char* argv[]) result = t.elapsed(); cout << "std::copy: " << result << endl; - // cache load: - opt::detail::copier::do_copy(ci_array, ci_array + array_size, i_array); - - // time unoptimised version: - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::detail::copier::do_copy(ci_array, ci_array + array_size, i_array); - } - result = t.elapsed(); - cout << "standard \"unoptimised\" copy: " << result << endl << endl; - // cache load: opt::copy(cc_array, cc_array + array_size, c_array); @@ -212,18 +150,6 @@ int cpp_main(int argc, char* argv[]) result = t.elapsed(); cout << "std::copy: " << result << endl; - // cache load: - opt::detail::copier::do_copy(cc_array, cc_array + array_size, c_array); - - // time unoptimised version: - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::detail::copier::do_copy(cc_array, cc_array + array_size, c_array); - } - result = t.elapsed(); - cout << "standard \"unoptimised\" copy: " << result << endl << endl; - return 0; } diff --git a/examples/fill_example.cpp b/examples/fill_example.cpp index 064a86e..67a9bca 100644 --- a/examples/fill_example.cpp +++ b/examples/fill_example.cpp @@ -1,7 +1,7 @@ /* * - * (C) Copyright John Maddock 1999. + * (C) Copyright John Maddock 1999-2005. * 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) @@ -20,9 +20,9 @@ #include #include +#include #include #include -#include #if defined(BOOST_NO_STDC_NAMESPACE) || (defined(std) && defined(__SGI_STL_PORT)) namespace std{ using :: memset; } @@ -35,13 +35,12 @@ using std::cin; namespace opt{ // // fill -// same as std::fill, uses memset where appropriate, along with call_traits -// to "optimise" parameter passing. +// same as std::fill, but uses memset where appropriate // namespace detail{ -template -void do_fill_(I first, I last, typename boost::call_traits::param_type val) +template +void do_fill(I first, I last, const T& val, const boost::integral_constant&) { while(first != last) { @@ -50,43 +49,24 @@ void do_fill_(I first, I last, typename boost::call_traits::param_type val) } } -template -struct filler +template +void do_fill(T* first, T* last, const T& val, const boost::true_type&) { - template - struct rebind - { - static void do_fill(I first, I last, typename boost::call_traits::param_type val) - { do_fill_(first, last, val); } - }; -}; - -template <> -struct filler -{ - template - struct rebind - { - static void do_fill(I first, I last, T val) - { - std::memset(first, val, last-first); - } - }; -}; + std::memset(first, val, last-first); +} } template inline void fill(I first, I last, const T& val) { - typedef detail::filler< - ::boost::type_traits::ice_and< - ::boost::is_pointer::value, - ::boost::is_arithmetic::value, - (sizeof(T) == 1) - >::value> filler_t; - typedef typename filler_t:: template rebind binder; - binder::do_fill(first, last, 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::value && (sizeof(T) == 1)> truth_type; + detail::do_fill(first, last, val, truth_type()); } }; // namespace opt @@ -150,8 +130,7 @@ int cpp_main(int argc, char* argv[]) result = t.elapsed(); cout << "std::fill: " << result << endl << endl; - cout << "testing fill(int)...\n" - "[Tests the effect of call_traits pass-by-value optimisation -\nthe value of this optimisation may depend upon hardware characteristics.]" << endl; + cout << "testing fill(int)...\n" << endl; // cache load: opt::fill(i_array, i_array + array_size, 3); diff --git a/examples/iter_swap_example.cpp b/examples/iter_swap_example.cpp index c5008a9..a1f30f1 100644 --- a/examples/iter_swap_example.cpp +++ b/examples/iter_swap_example.cpp @@ -1,7 +1,7 @@ /* * - * (C) Copyright John Maddock 1999. + * (C) Copyright John Maddock 1999-2005. * 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) @@ -22,6 +22,7 @@ #include #include +#include #include using std::cout; @@ -37,47 +38,39 @@ namespace opt{ // namespace detail{ -template -struct swapper +template +static void do_swap(I one, I two, const boost::false_type&) { - template - static void do_swap(I one, I two) - { - typedef typename std::iterator_traits::value_type v_t; - v_t v = *one; - *one = *two; - *two = v; - } -}; - -#ifdef __GNUC__ -using std::swap; -#endif - -template <> -struct swapper + typedef typename std::iterator_traits::value_type v_t; + v_t v = *one; + *one = *two; + *two = v; +} +template +static void do_swap(I one, I two, const boost::true_type&) { - template - static void do_swap(I one, I two) - { - using std::swap; - swap(*one, *two); - } -}; + using std::swap; + swap(*one, *two); +} } template 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::reference r1_t; typedef typename std::iterator_traits::reference r2_t; - detail::swapper< - ::boost::type_traits::ice_and< - ::boost::is_reference::value, - ::boost::is_reference::value, - ::boost::is_same::value - >::value>::do_swap(one, two); + + typedef boost::integral_constant::value + && ::boost::is_reference::value + && ::boost::is_same::value> truth_type; + + detail::do_swap(one, two, truth_type()); } diff --git a/examples/trivial_destructor_example.cpp b/examples/trivial_destructor_example.cpp index 9d76fa2..49ee63a 100644 --- a/examples/trivial_destructor_example.cpp +++ b/examples/trivial_destructor_example.cpp @@ -1,7 +1,7 @@ /* * - * (C) Copyright John Maddock 1999. + * (C) Copyright John Maddock 1999-2005. * 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) @@ -15,7 +15,7 @@ #include - +#include #include #include @@ -33,22 +33,8 @@ namespace opt{ namespace detail{ -template -struct array_destroyer -{ - template - static void destroy_array(T* i, T* j){ do_destroy_array(i, j); } -}; - -template <> -struct array_destroyer -{ - template - static void destroy_array(T*, T*){} -}; - template -void do_destroy_array(T* first, T* last) +void do_destroy_array(T* first, T* last, const boost::false_type&) { while(first != last) { @@ -57,12 +43,17 @@ void do_destroy_array(T* first, T* last) } } +template +inline void do_destroy_array(T* first, T* last, const boost::true_type&) +{ +} + } // namespace detail template inline void destroy_array(T* p1, T* p2) { - detail::array_destroyer::value>::destroy_array(p1, p2); + detail::do_destroy_array(p1, p2, ::boost::has_trivial_destructor()); } //