Merge pull request #22 from glenfe/develop

Implement constexpr addressof
This commit is contained in:
Glen Fernandes
2017-01-31 08:47:51 -05:00
committed by GitHub
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, 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>
#include <boost/detail/workaround.hpp>
#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
{
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_; }
namespace boost {
namespace core {
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 &);
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) 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<null_type> {
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<const null_type> {
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<volatile null_type> {
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<const volatile null_type> {
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<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>
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 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
return address_of<T>::get(addressof_ref<T>(o), 0);
}
#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) )
namespace detail
template<class T>
constexpr BOOST_FORCEINLINE
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 >
BOOST_FORCEINLINE
typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] )
template<class T, std::size_t N>
BOOST_FORCEINLINE typename core::detail::add_pointer<T[N]>::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<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);
return &o;
}
#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_np_test.cpp ;
run addressof_fn_test.cpp ;
compile addressof_constexpr_test.cpp ;
run checked_delete_test.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