diff --git a/include/boost/core/addressof.hpp b/include/boost/core/addressof.hpp index efde98a..b73ea56 100644 --- a/include/boost/core/addressof.hpp +++ b/include/boost/core/addressof.hpp @@ -117,7 +117,6 @@ struct address_of { } /* detail */ #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 @@ -171,7 +170,7 @@ const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N] namespace detail { template -T&& addressof_declval() BOOST_NOEXCEPT; +T addressof_declval() BOOST_NOEXCEPT; template struct addressof_void { diff --git a/include/boost/core/pointer_traits.hpp b/include/boost/core/pointer_traits.hpp new file mode 100644 index 0000000..1923f4d --- /dev/null +++ b/include/boost/core/pointer_traits.hpp @@ -0,0 +1,244 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_CORE_POINTER_TRAITS_HPP +#define BOOST_CORE_POINTER_TRAITS_HPP + +#include +#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) +#include +#else +#include +#endif + +namespace boost { + +template +struct pointer_traits; + +namespace detail { + +template +static typename boost::pointer_traits::element_type* +ptr_traits_address(U v) BOOST_NOEXCEPT +{ + return boost::pointer_traits::to_address(v); +} + +} /* detail */ + +#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) +template +struct pointer_traits + : std::pointer_traits { + template + struct rebind_to { + typedef typename std::pointer_traits::template rebind type; + }; + static typename std::pointer_traits::element_type* + to_address(T v) BOOST_NOEXCEPT { + return detail::ptr_traits_address(v.operator->()); + } +}; + +template +struct pointer_traits + : std::pointer_traits { + template + struct rebind_to { + typedef U* type; + }; + static T* to_address(T* v) BOOST_NOEXCEPT { + return v; + } +}; +#else +namespace detail { + +struct ptr_traits_none { char first, second; }; + +template +struct ptr_traits_has_element { +private: + template + static ptr_traits_none call(...); + template + static char call(typename U::element_type* = 0); +public: + static const bool value = sizeof(call(0)) == 1; +}; + +template +struct ptr_traits_first; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +template class T, class U, class... Args> +struct ptr_traits_first > { + typedef U type; +}; +#else +template class T, class U> +struct ptr_traits_first > { + typedef U type; +}; + +template class T, class U1, class U2> +struct ptr_traits_first > { + typedef U1 type; +}; + +template class T, class U1, class U2, class U3> +struct ptr_traits_first > { + typedef U1 type; +}; +#endif + +template::value> +struct ptr_traits_element { + typedef typename T::element_type type; +}; + +template +struct ptr_traits_element { + typedef typename ptr_traits_first::type type; +}; + +template +struct ptr_traits_has_difference { +private: + template + static ptr_traits_none call(...); + template + static char call(typename U::difference_type* = 0); +public: + static const bool value = sizeof(call(0)) == 1; +}; + +template::value> +struct ptr_traits_difference { + typedef typename T::difference_type type; +}; + +template +struct ptr_traits_difference { + typedef std::ptrdiff_t type; +}; + +template +struct ptr_traits_has_rebind { +private: + template + static ptr_traits_none call(...); + template + static char call(typename U::template rebind* = 0); +public: + static const bool value = sizeof(call(0)) == 1; +}; + +template +struct ptr_traits_rebind_to; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +template class T, class U, class... Args, class V> +struct ptr_traits_rebind_to, V> { + typedef T type; +}; +#else +template class T, class U, class V> +struct ptr_traits_rebind_to, V> { + typedef T type; +}; + +template class T, class U1, class U2, class V> +struct ptr_traits_rebind_to, V> { + typedef T type; +}; + +template class T, + class U1, class U2, class U3, class V> +struct ptr_traits_rebind_to, V> { + typedef T type; +}; +#endif + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +template::value> +struct ptr_traits_rebind { + typedef typename T::template rebind type; +}; + +template +struct ptr_traits_rebind { + typedef typename ptr_traits_rebind_to::type type; +}; +#else +template +struct ptr_traits_rebind { + typedef typename ptr_traits_rebind_to::type type; +}; +#endif + +template +struct ptr_traits_value { + typedef T type; +}; + +template<> +struct ptr_traits_value { + typedef struct { } type; +}; + +} /* detail */ + +template +struct pointer_traits { + typedef T pointer; + typedef typename detail::ptr_traits_element::type element_type; + typedef typename detail::ptr_traits_difference::type difference_type; + template + struct rebind_to { + typedef typename detail::ptr_traits_rebind::type type; + }; +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + using rebind = typename detail::ptr_traits_rebind::type; +#endif + static pointer + pointer_to(typename detail::ptr_traits_value::type& v) { + return pointer::pointer_to(v); + } + static element_type* to_address(pointer v) BOOST_NOEXCEPT { + return detail::ptr_traits_address(v.operator->()); + } +}; + +template +struct pointer_traits { + typedef T* pointer; + typedef T element_type; + typedef std::ptrdiff_t difference_type; + template + struct rebind_to { + typedef U* type; + }; +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + using rebind = U*; +#endif + static T* + pointer_to(typename detail::ptr_traits_value::type& v) BOOST_NOEXCEPT { + return addressof(v); + } + static T* to_address(T* v) BOOST_NOEXCEPT { + return v; + } +}; +#endif + +} /* boost */ + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fded1cd..5e0e5d3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -105,5 +105,12 @@ compile-fail scoped_enum_compile_fail_conv_to_int.cpp ; run underlying_type.cpp ; +run pointer_traits_to_address_test.cpp ; +run pointer_traits_pointer_test.cpp ; +run pointer_traits_element_type_test.cpp ; +run pointer_traits_difference_type_test.cpp ; +run pointer_traits_rebind_test.cpp ; +run pointer_traits_pointer_to_test.cpp ; + use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/get_pointer_test.cpp b/test/get_pointer_test.cpp index bf981cf..1ddf3be 100644 --- a/test/get_pointer_test.cpp +++ b/test/get_pointer_test.cpp @@ -1,7 +1,7 @@ // // get_pointer_test.cpp // -// Copyright 2014 Peter Dimov +// Copyright 2014, 2017 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at @@ -27,11 +27,23 @@ int main() delete p; } + { + X * p = 0; + BOOST_TEST( get_pointer( p ) == 0 ); + } + #if !defined( BOOST_NO_AUTO_PTR ) + { std::auto_ptr< X > p( new X ); BOOST_TEST( get_pointer( p ) == p.get() ); } + + { + std::auto_ptr< X > p; + BOOST_TEST( get_pointer( p ) == 0 ); + } + #endif #if !defined( BOOST_NO_CXX11_SMART_PTR ) @@ -41,11 +53,21 @@ int main() BOOST_TEST( get_pointer( p ) == p.get() ); } + { + std::unique_ptr< X > p; + BOOST_TEST( get_pointer( p ) == 0 ); + } + { std::shared_ptr< X > p( new X ); BOOST_TEST( get_pointer( p ) == p.get() ); } + { + std::shared_ptr< X > p; + BOOST_TEST( get_pointer( p ) == 0 ); + } + #endif return boost::report_errors(); diff --git a/test/pointer_traits_difference_type_test.cpp b/test/pointer_traits_difference_type_test.cpp new file mode 100644 index 0000000..e9d0b09 --- /dev/null +++ b/test/pointer_traits_difference_type_test.cpp @@ -0,0 +1,41 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +template +struct P { }; + +template +struct E { + typedef long difference_type; +}; + +int main() +{ + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); + return boost::report_errors(); +} diff --git a/test/pointer_traits_element_type_test.cpp b/test/pointer_traits_element_type_test.cpp new file mode 100644 index 0000000..a20733e --- /dev/null +++ b/test/pointer_traits_element_type_test.cpp @@ -0,0 +1,83 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +template +struct P1 { }; + +template +struct P2 { }; + +template +struct P3 { }; + +template +struct E1 { + typedef bool element_type; +}; + +template +struct E2 { + typedef bool element_type; +}; + +template +struct E3 { + typedef bool element_type; +}; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +template +struct P { }; + +template +struct E { + typedef bool element_type; +}; +#endif + +int main() +{ + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); +#endif + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); +#endif + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); + return boost::report_errors(); +} diff --git a/test/pointer_traits_pointer_test.cpp b/test/pointer_traits_pointer_test.cpp new file mode 100644 index 0000000..a98eb4d --- /dev/null +++ b/test/pointer_traits_pointer_test.cpp @@ -0,0 +1,30 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +template +struct P { }; + +int main() +{ + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::pointer>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::pointer>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::pointer>)); + return boost::report_errors(); +} diff --git a/test/pointer_traits_pointer_to_test.cpp b/test/pointer_traits_pointer_to_test.cpp new file mode 100644 index 0000000..33e21ad --- /dev/null +++ b/test/pointer_traits_pointer_to_test.cpp @@ -0,0 +1,63 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +class pointer { +public: + typedef typename boost::pointer_traits::element_type element_type; + pointer(T value) + : value_(value) { } + T get() const BOOST_NOEXCEPT { + return value_; + } + static pointer pointer_to(element_type& value) { + return pointer(&value); + } +private: + T value_; +}; + +template +inline bool +operator==(const pointer& lhs, const pointer& rhs) BOOST_NOEXCEPT +{ + return lhs.get() == rhs.get(); +} + +int main() +{ + int i = 0; + { + typedef int* type; + type p = &i; + BOOST_TEST(boost::pointer_traits::pointer_to(i) == p); + } + { + typedef pointer type; + type p(&i); + BOOST_TEST(boost::pointer_traits::pointer_to(i) == p); + } + { + typedef pointer > type; + type p(&i); + BOOST_TEST(boost::pointer_traits::pointer_to(i) == p); + } + { + typedef const int* type; + type p = &i; + BOOST_TEST(boost::pointer_traits::pointer_to(i) == p); + } + { + typedef pointer type; + type p(&i); + BOOST_TEST(boost::pointer_traits::pointer_to(i) == p); + } + return boost::report_errors(); +} diff --git a/test/pointer_traits_rebind_test.cpp b/test/pointer_traits_rebind_test.cpp new file mode 100644 index 0000000..999d195 --- /dev/null +++ b/test/pointer_traits_rebind_test.cpp @@ -0,0 +1,107 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +template +struct P1 { }; + +template +struct P2 { }; + +template +struct P3 { }; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +template +struct E1 { + template + using rebind = E1; +}; + +template +struct E2 { + template + using rebind = E2; +}; + +template +struct E3 { + template + using rebind = E3; +}; +#endif + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +template +struct P { }; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +template +struct E { + template + using rebind = E; +}; +#endif +#endif + +struct R { }; + +int main() +{ + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); +#endif + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); +#endif + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + boost::pointer_traits >::rebind_to::type>)); +#endif + return boost::report_errors(); +} diff --git a/test/pointer_traits_to_address_test.cpp b/test/pointer_traits_to_address_test.cpp new file mode 100644 index 0000000..3a86b42 --- /dev/null +++ b/test/pointer_traits_to_address_test.cpp @@ -0,0 +1,63 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +class pointer { +public: + typedef typename boost::pointer_traits::element_type element_type; + pointer(T value) + : value_(value) { } + T operator->() const BOOST_NOEXCEPT { + return value_; + } +private: + T value_; +}; + +int main() +{ + int i = 0; + { + typedef int* type; + type p = &i; + BOOST_TEST(boost::pointer_traits::to_address(p) == &i); + } + { + typedef pointer type; + type p(&i); + BOOST_TEST(boost::pointer_traits::to_address(p) == &i); + } + { + typedef pointer > type; + type p(&i); + BOOST_TEST(boost::pointer_traits::to_address(p) == &i); + } + { + typedef void* type; + type p = &i; + BOOST_TEST(boost::pointer_traits::to_address(p) == &i); + } + { + typedef pointer type; + type p(&i); + BOOST_TEST(boost::pointer_traits::to_address(p) == &i); + } + { + typedef const int* type; + type p = &i; + BOOST_TEST(boost::pointer_traits::to_address(p) == &i); + } + { + typedef pointer type; + type p(&i); + BOOST_TEST(boost::pointer_traits::to_address(p) == &i); + } + return boost::report_errors(); +}