Implement constexpr addressof

This commit is contained in:
Glen Fernandes
2017-01-30 17:34:49 -05:00
parent fa88cc32cf
commit 09dcc68ecd
3 changed files with 224 additions and 114 deletions

View File

@ -1,162 +1,250 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com) /*
// Douglas Gregor (gregod@cs.rpi.edu) 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)
// 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 #ifndef BOOST_CORE_ADDRESSOF_HPP
#define BOOST_CORE_ADDRESSOF_HPP #define BOOST_CORE_ADDRESSOF_HPP
# include <boost/config.hpp> #include <boost/config.hpp>
# include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
# include <cstddef> #include <cstddef>
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 namespace boost {
{ namespace core {
namespace detail {
template<class T> struct addr_impl_ref
{
T & v_;
BOOST_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {}
BOOST_FORCEINLINE operator T& () const { return v_; }
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: private:
addr_impl_ref & operator=(const addr_impl_ref &); T& o_;
}; };
template<class T> struct addressof_impl template<class T>
{ struct address_of {
static BOOST_FORCEINLINE T * f( T & v, long ) static BOOST_FORCEINLINE T* get(T& o, long) BOOST_NOEXCEPT {
{ return reinterpret_cast<T*>(&
return reinterpret_cast<T*>( const_cast<char&>(reinterpret_cast<const volatile char&>(o)));
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
} }
static BOOST_FORCEINLINE T* get(T* p, int) BOOST_NOEXCEPT {
static BOOST_FORCEINLINE T * f( T * v, int ) return p;
{
return v;
} }
}; };
#if !defined( BOOST_NO_CXX11_NULLPTR ) #if !defined(BOOST_NO_CXX11_NULLPTR)
#if !defined(BOOST_NO_CXX11_DECLTYPE) && \
#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) ) (defined(__INTEL_COMPILER) || \
(defined(__clang__) && !defined(_LIBCPP_VERSION)))
typedef decltype(nullptr) addr_nullptr_t; typedef decltype(nullptr) null_type;
#else #else
typedef std::nullptr_t null_type;
typedef std::nullptr_t addr_nullptr_t;
#endif #endif
template<> struct addressof_impl< addr_nullptr_t > template<>
{ struct address_of<null_type> {
typedef addr_nullptr_t T; typedef null_type type;
static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
static BOOST_FORCEINLINE T * f( T & v, int ) return &o;
{
return &v;
} }
}; };
template<> struct addressof_impl< addr_nullptr_t const > template<>
{ struct address_of<const null_type> {
typedef addr_nullptr_t const T; typedef const null_type type;
static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
static BOOST_FORCEINLINE T * f( T & v, int ) return &o;
{
return &v;
} }
}; };
template<> struct addressof_impl< addr_nullptr_t volatile > template<>
{ struct address_of<volatile null_type> {
typedef addr_nullptr_t volatile T; typedef volatile null_type type;
static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
static BOOST_FORCEINLINE T * f( T & v, int ) return &o;
{
return &v;
} }
}; };
template<> struct addressof_impl< addr_nullptr_t const volatile > template<>
{ struct address_of<const volatile null_type> {
typedef addr_nullptr_t const volatile T; typedef const volatile null_type type;
static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
static BOOST_FORCEINLINE T * f( T & v, int ) return &o;
{
return &v;
} }
}; };
#endif #endif
} // namespace detail #if defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF)
template<class T>
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<T>::get(o, 0);
#else
return address_of<T>::get(addressof_ref<T>(o), 0);
#endif
}
#else
template<class T>
struct add_rvalue_reference {
typedef T&& type;
};
template<class T>
typename add_rvalue_reference<T>::type declval() BOOST_NOEXCEPT;
template<class>
struct make_void {
typedef void type;
};
template<class T, class E = void>
struct has_member_address_operator {
static constexpr bool value = false;
};
template<class T>
struct has_member_address_operator<T,
typename make_void<decltype(declval<T&>().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<class T, class E = void>
struct has_non_member_address_operator {
static constexpr bool value = false;
};
template<class T>
struct has_non_member_address_operator<T,
typename make_void<decltype(operator&(declval<T&>()))>::type> {
static constexpr bool value = true;
};
template<class T, class E = void>
struct is_addressable {
static constexpr bool value = false;
};
template<class T>
struct is_addressable<T,
typename make_void<decltype(&declval<T&>())>::type> {
static constexpr bool value = true;
};
template<class T>
struct has_constexpr_address {
static constexpr bool value = is_addressable<T>::value &&
!has_member_address_operator<T>::value &&
!has_non_member_address_operator<T>::value;
};
template<bool E, class T>
struct address_if { };
template<class T>
struct address_if<true, T> {
typedef T* type;
};
template<class T> template<class T>
BOOST_FORCEINLINE BOOST_FORCEINLINE
T * addressof( T & v ) typename address_if<!has_constexpr_address<T>::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 address_of<T>::get(addressof_ref<T>(o), 0);
return boost::detail::addressof_impl<T>::f( v, 0 );
#else
return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 );
#endif
} }
#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) ) template<class T>
constexpr BOOST_FORCEINLINE
namespace detail typename address_if<has_constexpr_address<T>::value, T>::type
addressof(T& o) BOOST_NOEXCEPT
{ {
return &o;
}
#endif
template<class T> struct addressof_addp } /* detail */
} /* core */
template<class T>
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<class T>
struct add_pointer {
typedef T* type;
}; };
} // namespace detail } /* detail */
} /* core */
template< class T, std::size_t N > template<class T, std::size_t N>
BOOST_FORCEINLINE BOOST_FORCEINLINE typename core::detail::add_pointer<T[N]>::type
typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] ) addressof(T (&o)[N]) BOOST_NOEXCEPT
{ {
return &t; return &o;
}
#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]
{
return reinterpret_cast<T(*)[N]>(&t);
}
template<typename T,std::size_t N>
BOOST_FORCEINLINE
const T (*addressof(const T (&t)[N]))[N]
{
return reinterpret_cast<const T(*)[N]>(&t);
} }
#endif #endif
} // namespace boost #if defined(__BORLANDC__) && \
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);
}
#endif // BOOST_CORE_ADDRESSOF_HPP template<class T, std::size_t N>
BOOST_FORCEINLINE
const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N]
{
return reinterpret_cast<const T(*)[N]>(&o);
}
#endif
#endif
} /* boost */
#endif

View File

@ -13,6 +13,7 @@ run addressof_test.cpp ;
run addressof_test2.cpp ; run addressof_test2.cpp ;
run addressof_np_test.cpp ; run addressof_np_test.cpp ;
run addressof_fn_test.cpp ; run addressof_fn_test.cpp ;
compile addressof_constexpr_test.cpp ;
run checked_delete_test.cpp ; run checked_delete_test.cpp ;
compile-fail checked_delete_fail.cpp ; compile-fail checked_delete_fail.cpp ;

View File

@ -0,0 +1,21 @@
/*
Copyright 2017 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
*/
#include <boost/core/addressof.hpp>
#include <boost/static_assert.hpp>
#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