Implement pointer_traits::to_address as in P0653r0 * include/bits/allocated_ptr.h (allocated_ptr): Use pointer_traits::to_address. * include/bits/ptr_traits.h (pointer_traits): Implement to_address. * include/ext/pointer.h (pointer_traits): Define to_address in pointer_traits specialization. * testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc: Define operator->. * testsuite/20_util/pointer_traits/to_address.cc: New tests.
Tested i686-pc-linux-gnu. Glen
commit 7180839baa6dff48dc7a1536a2de0688f79d38dc Author: Glen Fernandes <glenj...@gmail.com> Date: Sun Jul 16 16:49:18 2017 -0400 Implement pointer_traits::to_address as in P0653r0 * include/bits/allocated_ptr.h (allocated_ptr): Use pointer_traits::to_address. * include/bits/ptr_traits.h (pointer_traits): Implement to_address. * include/ext/pointer.h (pointer_traits): Define to_address in pointer_traits specialization. * testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc: Define operator->. * testsuite/20_util/pointer_traits/to_address.cc: New tests. diff --git a/libstdc++-v3/include/bits/allocated_ptr.h b/libstdc++-v3/include/bits/allocated_ptr.h index 773b3f5..72e0179 100644 --- a/libstdc++-v3/include/bits/allocated_ptr.h +++ b/libstdc++-v3/include/bits/allocated_ptr.h @@ -82,16 +82,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Get the address that the owned pointer refers to. - value_type* get() { return _S_raw_ptr(_M_ptr); } + value_type* get() + { return std::pointer_traits<pointer>::to_address(_M_ptr); } private: - static value_type* _S_raw_ptr(value_type* __ptr) { return __ptr; } - - template<typename _Ptr> - static auto - _S_raw_ptr(_Ptr __ptr) -> decltype(_S_raw_ptr(__ptr.operator->())) - { return _S_raw_ptr(__ptr.operator->()); } - _Alloc* _M_alloc; pointer _M_ptr; }; diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index 797e7fc..93e95ad 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -111,6 +111,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION pointer_to(__make_not_void<element_type>& __e) { return _Ptr::pointer_to(__e); } + private: + template<typename _Tp> + static element_type* + __to_address(_Tp __p) noexcept + { return pointer_traits<_Tp>::to_address(__p); } + public: + /** + * @brief Obtain address referenced by a pointer to an object + * @param __p A pointer to an object + * @return @c pointer_traits<decltype(Expr)>::to_address(Expr) + where @c Expr is @c __p.operator->() + */ + static element_type* + to_address(pointer __p) noexcept + { return __to_address(__p.operator->()); } + static_assert(!is_same<element_type, __undefined>::value, "pointer type defines element_type or is like SomePointer<T, Args>"); }; @@ -140,6 +156,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static pointer pointer_to(__make_not_void<element_type>& __r) noexcept { return std::addressof(__r); } + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __p A pointer to an object + * @return @c __p + */ + static element_type* + to_address(pointer __p) noexcept { return __p; } }; /// Convenience alias for rebinding pointers. diff --git a/libstdc++-v3/include/ext/pointer.h b/libstdc++-v3/include/ext/pointer.h index 8432da0..d7ab4e2 100644 --- a/libstdc++-v3/include/ext/pointer.h +++ b/libstdc++-v3/include/ext/pointer.h @@ -584,6 +584,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static pointer pointer_to(typename pointer::reference __r) noexcept { return pointer(std::addressof(__r)); } + + static element_type* to_address(pointer __p) noexcept + { return __p.operator->(); } }; _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc index f54f793..a3ab52d 100644 --- a/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc +++ b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc @@ -28,12 +28,14 @@ struct P1 using difference_type = long; template<typename U> using rebind = P1<U>; static P1 pointer_to(T&) { return {}; } + T* operator->() const noexcept { return {}; } }; template<typename T> struct P2 { static P2 pointer_to(T&) { return {}; } + T* operator->() const noexcept { return {}; } }; namespace std diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/to_address.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/to_address.cc new file mode 100644 index 0000000..3c8cfbd --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/pointer_traits/to_address.cc @@ -0,0 +1,69 @@ +// { dg-do run { target c++11 } } + +// Copyright (C) 2011-2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + + +#include <memory> +#include <testsuite_hooks.h> + +struct P1 +{ + typedef int element_type; + int* value; + explicit P1(int* ptr) noexcept : value(ptr) { } + int* operator->() const noexcept { return value; } +}; + +struct P2 +{ + typedef P1::element_type element_type; + P1 value; + explicit P2(P1 ptr) noexcept : value(ptr) { } + P1 operator->() const noexcept { return value; } +}; + +void test01() +{ + int i = 0; + P1 p1( &i ); + VERIFY( std::pointer_traits<P1>::to_address(p1) == &i ); +} + +void test02() +{ + int i = 0; + P1 p1( &i ); + P2 p2( p1 ); + VERIFY( std::pointer_traits<P2>::to_address(p2) == &i ); +} + +void test03() +{ + int i = 0; + VERIFY( std::pointer_traits<int*>::to_address(&i) == &i ); + VERIFY( std::pointer_traits<const int*>::to_address(&i) == &i ); + VERIFY( std::pointer_traits<void*>::to_address(&i) == &i ); +} + +int main() +{ + test01(); + test02(); + test03(); + return 0; +}