diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index 889b582..a308da4 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -1,162 +1,250 @@ -// 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 -# include -# include +#include +#include +#include -namespace boost -{ +#if defined(BOOST_NO_SFINAE_EXPR) || \ + defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ + defined(BOOST_NO_CXX11_CONSTEXPR) || \ + defined(BOOST_NO_CXX11_DECLTYPE) || \ + (defined(BOOST_MSVC) && \ + BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))) +#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF +#endif -namespace detail -{ - -template struct addr_impl_ref -{ - T & v_; - - BOOST_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {} - BOOST_FORCEINLINE operator T& () const { return v_; } +namespace boost { +namespace core { +namespace detail { +template +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 &); + T& o_; }; -template struct addressof_impl -{ - static BOOST_FORCEINLINE T * f( T & v, long ) - { - return reinterpret_cast( - &const_cast(reinterpret_cast(v))); +template +struct address_of { + static BOOST_FORCEINLINE T* get(T& o, long) BOOST_NOEXCEPT { + return reinterpret_cast(& + const_cast(reinterpret_cast(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) null_type; #else - - typedef std::nullptr_t addr_nullptr_t; - +typedef std::nullptr_t null_type; #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 { + typedef null_type 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 { + typedef const null_type 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; - - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of { + typedef volatile null_type type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; -template<> struct addressof_impl< addr_nullptr_t const volatile > -{ - typedef addr_nullptr_t const volatile T; - - static BOOST_FORCEINLINE T * f( T & v, int ) - { - return &v; +template<> +struct address_of { + typedef const volatile null_type type; + static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { + return &o; } }; - #endif -} // namespace detail +#if defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) +template +BOOST_FORCEINLINE T* +addressof(T& o) BOOST_NOEXCEPT +{ +#if (defined(__BORLANDC__) && \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))) || \ + (defined(__SUNPRO_CC) && \ + BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)) + return address_of::get(o, 0); +#else + return address_of::get(addressof_ref(o), 0); +#endif +} +#else +template +struct add_rvalue_reference { + typedef T&& type; +}; + +template +typename add_rvalue_reference::type declval() BOOST_NOEXCEPT; + +template +struct make_void { + typedef void type; +}; + +template +struct has_member_address_operator { + static constexpr bool value = false; +}; + +template +struct has_member_address_operator().operator&())>::type> { + static constexpr bool value = true; +}; + +#if defined(BOOST_INTEL) && BOOST_WORKAROUND(BOOST_INTEL, < 1600) +struct addressable { }; + +addressable* operator&(addressable&) BOOST_NOEXCEPT; +#endif + +template +struct has_non_member_address_operator { + static constexpr bool value = false; +}; + +template +struct has_non_member_address_operator()))>::type> { + static constexpr bool value = true; +}; + +template +struct is_addressable { + static constexpr bool value = false; +}; + +template +struct is_addressable())>::type> { + static constexpr bool value = true; +}; + +template +struct has_constexpr_address { + static constexpr bool value = is_addressable::value && + !has_member_address_operator::value && + !has_non_member_address_operator::value; +}; + +template +struct address_if { }; + +template +struct address_if { + typedef T* type; +}; template BOOST_FORCEINLINE -T * addressof( T & v ) +typename address_if::value, T>::type +addressof(T& o) BOOST_NOEXCEPT { -#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || (defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)) - - return boost::detail::addressof_impl::f( v, 0 ); - -#else - - return boost::detail::addressof_impl::f( boost::detail::addr_impl_ref( v ), 0 ); - -#endif + return address_of::get(addressof_ref(o), 0); } -#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) ) - -namespace detail +template +constexpr BOOST_FORCEINLINE +typename address_if::value, T>::type +addressof(T& o) BOOST_NOEXCEPT { + return &o; +} +#endif -template struct addressof_addp +} /* detail */ +} /* core */ + +template +BOOST_CONSTEXPR BOOST_FORCEINLINE T* +addressof(T& o) BOOST_NOEXCEPT { - typedef T * type; + return core::detail::addressof(o); +} + +#if defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) +#if defined(__SUNPRO_CC) && \ + BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +namespace core { +namespace detail { + +template +struct add_pointer { + typedef T* type; }; -} // namespace detail +} /* detail */ +} /* core */ -template< class T, std::size_t N > -BOOST_FORCEINLINE -typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] ) +template +BOOST_FORCEINLINE typename core::detail::add_pointer::type +addressof(T (&o)[N]) BOOST_NOEXCEPT { - return &t; -} - -#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 -BOOST_FORCEINLINE -T (*addressof(T (&t)[N]))[N] -{ - return reinterpret_cast(&t); -} - -template -BOOST_FORCEINLINE -const T (*addressof(const T (&t)[N]))[N] -{ - return reinterpret_cast(&t); + return &o; } #endif -} // namespace boost +#if defined(__BORLANDC__) && \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +template +BOOST_FORCEINLINE +T (*addressof(T (&o)[N]) BOOST_NOEXCEPT)[N] +{ + return reinterpret_cast(&o); +} -#endif // BOOST_CORE_ADDRESSOF_HPP +template +BOOST_FORCEINLINE +const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N] +{ + return reinterpret_cast(&o); +} +#endif +#endif + +} /* boost */ + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f40577d..64cde15 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -13,6 +13,7 @@ run addressof_test.cpp ; run addressof_test2.cpp ; run addressof_np_test.cpp ; run addressof_fn_test.cpp ; +compile addressof_constexpr_test.cpp ; run checked_delete_test.cpp ; compile-fail checked_delete_fail.cpp ; diff --git a/test/addressof_constexpr_test.cpp b/test/addressof_constexpr_test.cpp new file mode 100644 index 0000000..9d93565 --- /dev/null +++ b/test/addressof_constexpr_test.cpp @@ -0,0 +1,21 @@ +/* +Copyright 2017 Glen Joseph Fernandes + + +Distributed under the Boost Software +License, Version 1.0. +http://boost.org/LICENSE_1_0.txt +*/ + +#include +#include + +#if !defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) +struct Type { }; + +static int v1 = 0; +static Type v2 = { }; + +BOOST_STATIC_ASSERT(boost::addressof(v1) == &v1); +BOOST_STATIC_ASSERT(boost::addressof(v2) == &v2); +#endif