From 0f24897958736c83b75b3c28078660582bb13be3 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:07:19 +0000 Subject: [PATCH] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41369] --- .../boost/functional/detail/container_fwd.hpp | 6 +- .../functional/detail/float_functions.hpp | 6 +- .../boost/functional/detail/hash_float.hpp | 115 ++++++++++--- include/boost/functional/hash.hpp | 6 +- include/boost/functional/hash/deque.hpp | 14 +- include/boost/functional/hash/hash.hpp | 155 ++++++++++++++---- include/boost/functional/hash/list.hpp | 14 +- include/boost/functional/hash/map.hpp | 15 +- include/boost/functional/hash/pair.hpp | 13 +- include/boost/functional/hash/set.hpp | 14 +- include/boost/functional/hash/vector.hpp | 13 +- include/boost/functional/hash_fwd.hpp | 6 +- 12 files changed, 283 insertions(+), 94 deletions(-) diff --git a/include/boost/functional/detail/container_fwd.hpp b/include/boost/functional/detail/container_fwd.hpp index d30bef3..f3f82f2 100644 --- a/include/boost/functional/detail/container_fwd.hpp +++ b/include/boost/functional/detail/container_fwd.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) #if !defined(BOOST_DETAIL_CONTAINER_FWD_HPP) #define BOOST_DETAIL_CONTAINER_FWD_HPP diff --git a/include/boost/functional/detail/float_functions.hpp b/include/boost/functional/detail/float_functions.hpp index 34b8251..9aac5a2 100644 --- a/include/boost/functional/detail/float_functions.hpp +++ b/include/boost/functional/detail/float_functions.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) #if !defined(BOOST_FUNCTIONAL_DETAIL_FLOAT_FUNCTIONS_HPP) #define BOOST_FUNCTIONAL_DETAIL_FLOAT_FUNCTIONS_HPP diff --git a/include/boost/functional/detail/hash_float.hpp b/include/boost/functional/detail/hash_float.hpp index 07d19c3..d005e7d 100644 --- a/include/boost/functional/detail/hash_float.hpp +++ b/include/boost/functional/detail/hash_float.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -15,24 +15,40 @@ #endif #include +#include +#include #include #include -#include -// Don't use fpclassify or _fpclass for stlport. -#if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) -# if defined(__GLIBCPP__) || defined(__GLIBCXX__) -// GNU libstdc++ 3 -# if (defined(__USE_ISOC99) || defined(_GLIBCXX_USE_C99_MATH)) && \ - !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) -# define BOOST_HASH_USE_FPCLASSIFY -# endif -# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) -// Dinkumware Library, on Visual C++ -# if defined(BOOST_MSVC) -# define BOOST_HASH_USE_FPCLASS -# endif +// Select implementation for the current platform. + +// Cygwn +#if defined(__CYGWIN__) +# if defined(__i386__) || defined(_M_IX86) +# define BOOST_HASH_USE_x86_BINARY_HASH # endif + +// STLport +#elif defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) +// _fpclass and fpclassify aren't good enough on STLport. + +// GNU libstdc++ 3 +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) +# if (defined(__USE_ISOC99) || defined(_GLIBCXX_USE_C99_MATH)) && \ + !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) +# define BOOST_HASH_USE_FPCLASSIFY +# endif + +// Dinkumware Library, on Visual C++ +#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) + +// Not using _fpclass because it causes a warning about a conversion +// from 'long double' to 'double'. Pity. +// +//# if defined(BOOST_MSVC) +//# define BOOST_HASH_USE_FPCLASS +//# endif + #endif namespace boost @@ -44,25 +60,69 @@ namespace boost seed ^= value + (seed<<6) + (seed>>2); } +// A simple, non-portable hash algorithm for x86. +#if defined(BOOST_HASH_USE_x86_BINARY_HASH) + inline std::size_t float_hash_impl(float v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr; + return seed; + } + + inline std::size_t float_hash_impl(double v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr++; + hash_float_combine(seed, *ptr); + return seed; + } + + inline std::size_t float_hash_impl(long double v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr++; + hash_float_combine(seed, *ptr++); + hash_float_combine(seed, *(boost::uint16_t*)ptr); + return seed; + } + +#else + template inline std::size_t float_hash_impl(T v) { int exp = 0; - errno = 0; + v = boost::hash_detail::call_frexp(v, &exp); - if(errno) return 0; - std::size_t seed = 0; + // A postive value is easier to hash, so combine the + // sign with the exponent. + if(v < 0) { + v = -v; + exp += std::numeric_limits::max_exponent - + std::numeric_limits::min_exponent; + } + // The result of frexp is always between 0.5 and 1, so its + // top bit will always be 1. Subtract by 0.5 to remove that. + v -= T(0.5); + v = boost::hash_detail::call_ldexp(v, + std::numeric_limits::digits + 1); + std::size_t seed = static_cast(v); + v -= seed; + + // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1; std::size_t const length - = (std::numeric_limits::digits + - std::numeric_limits::digits - 1) - / std::numeric_limits::digits; + = (std::numeric_limits::digits * + boost::static_log2::radix>::value + - 1) + / std::numeric_limits::digits; - for(std::size_t i = 0; i < length; ++i) + for(std::size_t i = 0; i != length; ++i) { - v = boost::hash_detail::call_ldexp(v, std::numeric_limits::digits); - int const part = static_cast(v); + v = boost::hash_detail::call_ldexp(v, + std::numeric_limits::digits); + std::size_t part = static_cast(v); v -= part; hash_float_combine(seed, part); } @@ -71,6 +131,7 @@ namespace boost return seed; } +#endif template inline std::size_t float_hash_value(T v) @@ -114,7 +175,7 @@ namespace boost return 0; } #else - return float_hash_impl(v); + return v == 0 ? 0 : float_hash_impl(v); #endif } } diff --git a/include/boost/functional/hash.hpp b/include/boost/functional/hash.hpp index 65e19b1..60b2608 100644 --- a/include/boost/functional/hash.hpp +++ b/include/boost/functional/hash.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf diff --git a/include/boost/functional/hash/deque.hpp b/include/boost/functional/hash/deque.hpp index 0f688cd..8e92727 100644 --- a/include/boost/functional/hash/deque.hpp +++ b/include/boost/functional/hash/deque.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -14,8 +14,14 @@ # pragma once #endif +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/deque.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) #warning "boost/functional/hash/deque.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + #include #endif - diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index 993977e..5515efd 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/hash/hash.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2007. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -28,29 +28,24 @@ #include #endif -#if defined(BOOST_MSVC) -# pragma warning(push) -# pragma warning(disable:4267) -#endif - namespace boost { -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) - // Borland complains about an ambiguous function overload - // when compiling boost::hash. std::size_t hash_value(bool); -#endif - + std::size_t hash_value(char); + std::size_t hash_value(unsigned char); + std::size_t hash_value(signed char); + std::size_t hash_value(short); + std::size_t hash_value(unsigned short); std::size_t hash_value(int); std::size_t hash_value(unsigned int); std::size_t hash_value(long); std::size_t hash_value(unsigned long); -#if defined(BOOST_HAS_LONG_LONG) && defined(_M_X64) && defined(_WIN64) - // On 64-bit windows std::size_t is a typedef for unsigned long long, which - // isn't due to be supported until Boost 1.35. So add support here. - // (Technically, Boost.Hash isn't actually documented as supporting - // std::size_t. But it would be pretty silly not to). +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + std::size_t hash_value(wchar_t); +#endif + +#if defined(BOOST_HAS_LONG_LONG) std::size_t hash_value(long long); std::size_t hash_value(unsigned long long); #endif @@ -93,14 +88,84 @@ namespace boost template std::size_t hash_value(std::multimap const& v); + template + std::size_t hash_value(std::complex const&); + // Implementation -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + namespace hash_detail + { + template + inline std::size_t hash_value_signed(T val) + { + const int size_t_bits = std::numeric_limits::digits; + // ceiling(std::numeric_limits::digits / size_t_bits) - 1 + const int length = (std::numeric_limits::digits - 1) + / size_t_bits; + + std::size_t seed = 0; + T positive = val < 0 ? -1 - val : val; + + // Hopefully, this loop can be unrolled. + for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) + { + seed ^= (std::size_t) (positive >> i) + (seed<<6) + (seed>>2); + } + seed ^= (std::size_t) val + (seed<<6) + (seed>>2); + + return seed; + } + + template + inline std::size_t hash_value_unsigned(T val) + { + const int size_t_bits = std::numeric_limits::digits; + // ceiling(std::numeric_limits::digits / size_t_bits) - 1 + const int length = (std::numeric_limits::digits - 1) + / size_t_bits; + + std::size_t seed = 0; + + // Hopefully, this loop can be unrolled. + for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) + { + seed ^= (std::size_t) (val >> i) + (seed<<6) + (seed>>2); + } + seed ^= (std::size_t) val + (seed<<6) + (seed>>2); + + return seed; + } + } + inline std::size_t hash_value(bool v) { return static_cast(v); } -#endif + + inline std::size_t hash_value(char v) + { + return static_cast(v); + } + + inline std::size_t hash_value(unsigned char v) + { + return static_cast(v); + } + + inline std::size_t hash_value(signed char v) + { + return static_cast(v); + } + + inline std::size_t hash_value(short v) + { + return static_cast(v); + } + + inline std::size_t hash_value(unsigned short v) + { + return static_cast(v); + } inline std::size_t hash_value(int v) { @@ -122,15 +187,22 @@ namespace boost return static_cast(v); } -#if defined(BOOST_HAS_LONG_LONG) && defined(_M_X64) && defined(_WIN64) +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + inline std::size_t hash_value(wchar_t v) + { + return static_cast(v); + } +#endif + +#if defined(BOOST_HAS_LONG_LONG) inline std::size_t hash_value(long long v) { - return v; + return hash_detail::hash_value_signed(v); } inline std::size_t hash_value(unsigned long long v) { - return v; + return hash_detail::hash_value_unsigned(v); } #endif @@ -143,6 +215,7 @@ namespace boost { std::size_t x = static_cast( reinterpret_cast(v)); + return x + (x >> 3); } @@ -292,6 +365,15 @@ namespace boost return hash_range(v.begin(), v.end()); } + template + std::size_t hash_value(std::complex const& v) + { + boost::hash hasher; + std::size_t seed = hasher(v.imag()); + seed ^= hasher(v.real()) + (seed<<6) + (seed>>2); + return seed; + } + // // boost::hash // @@ -387,10 +469,17 @@ namespace boost struct hash : public std::unary_function { - std::size_t operator()(T* v) const \ - { \ - return boost::hash_value(v); \ - } \ + std::size_t operator()(T* v) const + { +#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) + return boost::hash_value(v); +#else + std::size_t x = static_cast( + reinterpret_cast(v)); + + return x + (x >> 3); +#endif + } }; #else namespace hash_detail @@ -407,7 +496,14 @@ namespace boost { std::size_t operator()(T val) const { +#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 590) return boost::hash_value(val); +#else + std::size_t x = static_cast( + reinterpret_cast(val)); + + return x + (x >> 3); +#endif } }; }; @@ -422,7 +518,6 @@ namespace boost } #endif // BOOST_FUNCTIONAL_HASH_HASH_HPP - //////////////////////////////////////////////////////////////////////////////// #if !defined(BOOST_HASH_NO_EXTENSIONS) \ @@ -594,9 +689,5 @@ namespace boost #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION } -#if defined(BOOST_MSVC) -# pragma warning(pop) -#endif - #endif diff --git a/include/boost/functional/hash/list.hpp b/include/boost/functional/hash/list.hpp index f332462..219394b 100644 --- a/include/boost/functional/hash/list.hpp +++ b/include/boost/functional/hash/list.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -14,8 +14,14 @@ # pragma once #endif +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/list.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) #warning "boost/functional/hash/list.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + #include #endif - diff --git a/include/boost/functional/hash/map.hpp b/include/boost/functional/hash/map.hpp index 10526a1..59e259f 100644 --- a/include/boost/functional/hash/map.hpp +++ b/include/boost/functional/hash/map.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -14,9 +14,14 @@ # pragma once #endif +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/map.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) #warning "boost/functional/hash/map.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + #include #endif - - diff --git a/include/boost/functional/hash/pair.hpp b/include/boost/functional/hash/pair.hpp index 9c54671..68f2233 100644 --- a/include/boost/functional/hash/pair.hpp +++ b/include/boost/functional/hash/pair.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -14,7 +14,14 @@ # pragma once #endif +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/pair.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) #warning "boost/functional/hash/pair.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + #include #endif diff --git a/include/boost/functional/hash/set.hpp b/include/boost/functional/hash/set.hpp index 53923e1..6e3ef71 100644 --- a/include/boost/functional/hash/set.hpp +++ b/include/boost/functional/hash/set.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -14,8 +14,14 @@ # pragma once #endif +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/set.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) #warning "boost/functional/hash/set.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + #include #endif - diff --git a/include/boost/functional/hash/vector.hpp b/include/boost/functional/hash/vector.hpp index 5a75f8c..eeadf4e 100644 --- a/include/boost/functional/hash/vector.hpp +++ b/include/boost/functional/hash/vector.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf @@ -14,7 +14,14 @@ # pragma once #endif +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/vector.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) #warning "boost/functional/hash/vector.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + #include #endif diff --git a/include/boost/functional/hash_fwd.hpp b/include/boost/functional/hash_fwd.hpp index dcbe659..4d103f7 100644 --- a/include/boost/functional/hash_fwd.hpp +++ b/include/boost/functional/hash_fwd.hpp @@ -1,7 +1,7 @@ -// Copyright Daniel James 2005-2006. 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) +// Copyright 2005-2007 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) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf