diff options
Diffstat (limited to 'boost/core/addressof.hpp')
-rw-r--r-- | boost/core/addressof.hpp | 301 |
1 files changed, 202 insertions, 99 deletions
diff --git a/boost/core/addressof.hpp b/boost/core/addressof.hpp index 889b5825e1..0a2b46be77 100644 --- a/boost/core/addressof.hpp +++ b/boost/core/addressof.hpp @@ -1,162 +1,265 @@ -// Copyright (C) 2002 Brad King (brad.king@kitware.com) -// Douglas Gregor (gregod@cs.rpi.edu) -// -// Copyright (C) 2002, 2008, 2013 Peter Dimov -// -// 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) +/* +Copyright (C) 2002 Brad King (brad.king@kitware.com) + Douglas Gregor (gregod@cs.rpi.edu) -// For more information, see http://www.boost.org +Copyright (C) 2002, 2008, 2013 Peter Dimov + +Copyright (C) 2017 Glen Joseph Fernandes (glenjofe@gmail.com) + +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) +*/ #ifndef BOOST_CORE_ADDRESSOF_HPP #define BOOST_CORE_ADDRESSOF_HPP -# include <boost/config.hpp> -# include <boost/detail/workaround.hpp> -# include <cstddef> +#include <boost/config.hpp> -namespace boost -{ +#if defined(BOOST_MSVC_FULL_VER) && BOOST_MSVC_FULL_VER >= 190024215 +#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF +#elif defined(BOOST_GCC) && BOOST_GCC >= 70000 +#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF +#elif defined(__has_builtin) +#if __has_builtin(__builtin_addressof) +#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF +#endif +#endif -namespace detail -{ +#if defined(BOOST_CORE_HAS_BUILTIN_ADDRESSOF) +#if defined(BOOST_NO_CXX11_CONSTEXPR) +#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF +#endif + +namespace boost { -template<class T> struct addr_impl_ref +template<class T> +BOOST_CONSTEXPR inline T* +addressof(T& o) BOOST_NOEXCEPT { - T & v_; + return __builtin_addressof(o); +} - BOOST_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {} - BOOST_FORCEINLINE operator T& () const { return v_; } +} /* boost */ +#else +#include <boost/detail/workaround.hpp> +#include <cstddef> +namespace boost { +namespace detail { + +template<class T> +class addressof_ref { +public: + BOOST_FORCEINLINE addressof_ref(T& o) BOOST_NOEXCEPT + : o_(o) { } + BOOST_FORCEINLINE operator T&() const BOOST_NOEXCEPT { + return o_; + } private: - addr_impl_ref & operator=(const addr_impl_ref &); + addressof_ref& operator=(const addressof_ref&); + T& o_; }; -template<class T> struct addressof_impl -{ - static BOOST_FORCEINLINE T * f( T & v, long ) - { - return reinterpret_cast<T*>( - &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); +template<class T> +struct address_of { + static BOOST_FORCEINLINE T* get(T& o, long) BOOST_NOEXCEPT { + return reinterpret_cast<T*>(& + const_cast<char&>(reinterpret_cast<const volatile char&>(o))); } - - static BOOST_FORCEINLINE T * f( T * v, int ) - { - return v; + static BOOST_FORCEINLINE T* get(T* p, int) BOOST_NOEXCEPT { + return p; } }; -#if !defined( BOOST_NO_CXX11_NULLPTR ) - -#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) ) - - typedef decltype(nullptr) addr_nullptr_t; - +#if !defined(BOOST_NO_CXX11_NULLPTR) +#if !defined(BOOST_NO_CXX11_DECLTYPE) && \ + (defined(__INTEL_COMPILER) || \ + (defined(__clang__) && !defined(_LIBCPP_VERSION))) +typedef decltype(nullptr) addressof_null_t; #else - - typedef std::nullptr_t addr_nullptr_t; - +typedef std::nullptr_t addressof_null_t; #endif -template<> struct addressof_impl< addr_nullptr_t > -{ - typedef addr_nullptr_t T; - - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of<addressof_null_t> { + typedef addressof_null_t type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; -template<> struct addressof_impl< addr_nullptr_t const > -{ - typedef addr_nullptr_t const T; - - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of<const addressof_null_t> { + typedef const addressof_null_t type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; -template<> struct addressof_impl< addr_nullptr_t volatile > -{ - typedef addr_nullptr_t volatile T; +template<> +struct address_of<volatile addressof_null_t> { + typedef volatile addressof_null_t type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; + } +}; - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of<const volatile addressof_null_t> { + typedef const volatile addressof_null_t type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; +#endif + +} /* detail */ -template<> struct addressof_impl< addr_nullptr_t const volatile > +#if defined(BOOST_NO_CXX11_SFINAE_EXPR) || \ + defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ + defined(BOOST_NO_CXX11_CONSTEXPR) || \ + defined(BOOST_NO_CXX11_DECLTYPE) +#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF + +template<class T> +BOOST_FORCEINLINE T* +addressof(T& o) BOOST_NOEXCEPT { - typedef addr_nullptr_t const volatile T; +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) || \ + BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120) + return detail::address_of<T>::get(o, 0); +#else + return detail::address_of<T>::get(detail::addressof_ref<T>(o), 0); +#endif +} - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; - } +#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +namespace detail { + +template<class T> +struct addressof_result { + typedef T* type; }; +} /* detail */ + +template<class T, std::size_t N> +BOOST_FORCEINLINE typename detail::addressof_result<T[N]>::type +addressof(T (&o)[N]) BOOST_NOEXCEPT +{ + return &o; +} #endif -} // namespace detail +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +template<class T, std::size_t N> +BOOST_FORCEINLINE +T (*addressof(T (&o)[N]) BOOST_NOEXCEPT)[N] +{ + return reinterpret_cast<T(*)[N]>(&o); +} -template<class T> +template<class T, std::size_t N> BOOST_FORCEINLINE -T * addressof( T & v ) +const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N] { -#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || (defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)) + return reinterpret_cast<const T(*)[N]>(&o); +} +#endif +#else +namespace detail { - return boost::detail::addressof_impl<T>::f( v, 0 ); +template<class T> +T&& addressof_declval() BOOST_NOEXCEPT; -#else +template<class> +struct addressof_void { + typedef void type; +}; - return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 ); +template<class T, class E = void> +struct addressof_member_operator { + static constexpr bool value = false; +}; + +template<class T> +struct addressof_member_operator<T, typename + addressof_void<decltype(addressof_declval<T&>().operator&())>::type> { + static constexpr bool value = true; +}; + +#if BOOST_WORKAROUND(BOOST_INTEL, < 1600) +struct addressof_addressable { }; +addressof_addressable* +operator&(addressof_addressable&) BOOST_NOEXCEPT; #endif -} -#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) ) +template<class T, class E = void> +struct addressof_non_member_operator { + static constexpr bool value = false; +}; -namespace detail -{ +template<class T> +struct addressof_non_member_operator<T, typename + addressof_void<decltype(operator&(addressof_declval<T&>()))>::type> { + static constexpr bool value = true; +}; -template<class T> struct addressof_addp -{ - typedef T * type; +template<class T, class E = void> +struct addressof_expression { + static constexpr bool value = false; +}; + +template<class T> +struct addressof_expression<T, + typename addressof_void<decltype(&addressof_declval<T&>())>::type> { + static constexpr bool value = true; +}; + +template<class T> +struct addressof_is_constexpr { + static constexpr bool value = addressof_expression<T>::value && + !addressof_member_operator<T>::value && + !addressof_non_member_operator<T>::value; }; -} // namespace detail +template<bool E, class T> +struct addressof_if { }; + +template<class T> +struct addressof_if<true, T> { + typedef T* type; +}; -template< class T, std::size_t N > +template<class T> BOOST_FORCEINLINE -typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] ) +typename addressof_if<!addressof_is_constexpr<T>::value, T>::type +addressof(T& o) BOOST_NOEXCEPT { - return &t; + return address_of<T>::get(addressof_ref<T>(o), 0); } -#endif - -// Borland doesn't like casting an array reference to a char reference -// but these overloads work around the problem. -#if defined( __BORLANDC__ ) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -template<typename T,std::size_t N> -BOOST_FORCEINLINE -T (*addressof(T (&t)[N]))[N] +template<class T> +constexpr BOOST_FORCEINLINE +typename addressof_if<addressof_is_constexpr<T>::value, T>::type +addressof(T& o) BOOST_NOEXCEPT { - return reinterpret_cast<T(*)[N]>(&t); + return &o; } -template<typename T,std::size_t N> -BOOST_FORCEINLINE -const T (*addressof(const T (&t)[N]))[N] +} /* detail */ + +template<class T> +constexpr BOOST_FORCEINLINE T* +addressof(T& o) BOOST_NOEXCEPT { - return reinterpret_cast<const T(*)[N]>(&t); + return detail::addressof(o); } #endif -} // namespace boost +} /* boost */ +#endif -#endif // BOOST_CORE_ADDRESSOF_HPP +#endif |