From 61cd19e6be197dbafa410e894f002a185256db30 Mon Sep 17 00:00:00 2001 From: Glen Joseph Fernandes Date: Tue, 28 Nov 2017 14:22:32 +0000 Subject: [PATCH] Add std::to_address for C++2a (P0653R2) 2017-11-28 Glen Joseph Fernandes * include/bits/ptr_traits.h (to_address): Implement to_address. * testsuite/20_util/to_address/1.cc: New test. From-SVN: r255199 --- libstdc++-v3/ChangeLog | 5 + libstdc++-v3/include/bits/ptr_traits.h | 39 +++++ .../testsuite/20_util/to_address/1.cc | 146 ++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 libstdc++-v3/testsuite/20_util/to_address/1.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 732d802b3b9..aa764f54702 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,8 @@ +2017-11-28 Glen Joseph Fernandes + + * include/bits/ptr_traits.h (to_address): Implement to_address. + * testsuite/20_util/to_address/1.cc: New test. + 2017-11-27 Stephan Bergmann * include/std/string_view (basic_string_view::find_first_of): Add diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index 74d4c18126c..67cc7e97a80 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -151,10 +151,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __to_address(_Tp* __ptr) noexcept { return __ptr; } +#if __cplusplus <= 201703L template constexpr typename std::pointer_traits<_Ptr>::element_type* __to_address(const _Ptr& __ptr) { return std::__to_address(__ptr.operator->()); } +#else + template + constexpr auto + __to_address(const _Ptr& __ptr) noexcept + -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) + { return std::pointer_traits<_Ptr>::to_address(__ptr); } + + template + constexpr auto + __to_address(const _Ptr& __ptr, _None...) noexcept + { return std::__to_address(__ptr.operator->()); } + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __ptr A pointer to an object + * @return @c __ptr + * @ingroup pointer_abstractions + */ + template + constexpr _Tp* + to_address(_Tp* __ptr) noexcept + { + static_assert(!std::is_function_v<_Tp>, "not a pointer to function"); + return __ptr; + } + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __ptr A pointer to an object + * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is + well-formed, otherwise @c to_address(__ptr.operator->()) + * @ingroup pointer_abstractions + */ + template + constexpr auto + to_address(const _Ptr& __ptr) noexcept + { return std::__to_address(__ptr); } +#endif // C++2a _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/testsuite/20_util/to_address/1.cc b/libstdc++-v3/testsuite/20_util/to_address/1.cc new file mode 100644 index 00000000000..627ca69fbb1 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/to_address/1.cc @@ -0,0 +1,146 @@ +// Copyright (C) 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +class P1 +{ +public: + using element_type = int; + + explicit P1(int* p) + : p_(p) { } + + int* operator->() const noexcept + { return p_; } + +private: + int* p_; +}; + +class P2 +{ +public: + using element_type = int; + + explicit P2(int* p) + : p_(p) { } + + P1 operator->() const noexcept + { return p_; } + +private: + P1 p_; +}; + +class P3 +{ +public: + explicit P3(int* p) + : p_(p) { } + + int* get() const noexcept + { return p_; } + +private: + int* p_; +}; + +namespace std +{ + template<> + struct pointer_traits<::P3> + { + static int* to_address(const ::P3& p) noexcept + { return p.get(); } + }; +} + +class P4 +{ +public: + explicit P4(int* p) + : p_(p) { } + + int* operator->() const noexcept + { return nullptr; } + + int* get() const noexcept + { return p_; } + +private: + int* p_; +}; + +namespace std +{ + template<> + struct pointer_traits<::P4> + { + static int* to_address(const ::P4& p) noexcept + { return p.get(); } + }; +} + +void test01() +{ + int i = 0; + int* p = &i; + VERIFY( std::to_address(p) == &i ); +} + +void test02() +{ + int i = 0; + P1 p(&i); + VERIFY( std::to_address(p) == &i ); +} + +void test03() +{ + int i = 0; + P2 p(&i); + VERIFY( std::to_address(p) == &i ); +} + +void test04() +{ + int i = 0; + P3 p(&i); + VERIFY( std::to_address(p) == &i ); +} + +void test05() +{ + int i = 0; + P4 p(&i); + VERIFY( std::to_address(p) == &i ); +} + +int main() +{ + test01(); + test02(); + test03(); + test04(); + test05(); + return 0; +}