diff options
author | Eric Fiselier <eric@efcs.ca> | 2017-11-22 19:49:21 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2017-11-22 19:49:21 +0000 |
commit | 3295274725ba7d941468deb388375a66afe78baf (patch) | |
tree | 15cef7d91580d363c0ba6cc6c76e58d5e3206bb9 | |
parent | 9180eb1f4ab96481413e93d35f35c3685de3084c (diff) | |
download | bcm5719-llvm-3295274725ba7d941468deb388375a66afe78baf.tar.gz bcm5719-llvm-3295274725ba7d941468deb388375a66afe78baf.zip |
[libcxx] Implement std::to_address for C++20
Summary: Now implements P0653R2 - Utility to convert to raw pointer.
Reviewers: mclow.lists, EricWF
Reviewed By: EricWF
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D35470
llvm-svn: 318865
-rw-r--r-- | libcxx/include/memory | 41 | ||||
-rw-r--r-- | libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp | 120 |
2 files changed, 160 insertions, 1 deletions
diff --git a/libcxx/include/memory b/libcxx/include/memory index 888ce692b90..913bc85c856 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -46,6 +46,9 @@ struct pointer_traits<T*> static pointer pointer_to(<details>) noexcept; }; +template <class T> constexpr T* to_address(T* p) noexcept; // C++20 +template <class Ptr> auto to_address(const Ptr& p) noexcept; // C++20 + template <class Alloc> struct allocator_traits { @@ -1090,13 +1093,14 @@ struct __const_void_pointer<_Ptr, _Alloc, false> }; template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _Tp* __to_raw_pointer(_Tp* __p) _NOEXCEPT { return __p; } +#if _LIBCPP_STD_VER <= 17 template <class _Pointer> inline _LIBCPP_INLINE_VISIBILITY typename pointer_traits<_Pointer>::element_type* @@ -1104,6 +1108,41 @@ __to_raw_pointer(_Pointer __p) _NOEXCEPT { return _VSTD::__to_raw_pointer(__p.operator->()); } +#else +template <class _Pointer> +inline _LIBCPP_INLINE_VISIBILITY +auto +__to_raw_pointer(const _Pointer& __p) _NOEXCEPT +-> decltype(pointer_traits<_Pointer>::to_address(__p)) +{ + return pointer_traits<_Pointer>::to_address(__p); +} + +template <class _Pointer, class... _None> +inline _LIBCPP_INLINE_VISIBILITY +auto +__to_raw_pointer(const _Pointer& __p, _None...) _NOEXCEPT +{ + return _VSTD::__to_raw_pointer(__p.operator->()); +} + +template <class _Tp> +inline _LIBCPP_INLINE_VISIBILITY constexpr +_Tp* +to_address(_Tp* __p) _NOEXCEPT +{ + static_assert(!is_function_v<_Tp>, "_Tp is a function type"); + return __p; +} + +template <class _Pointer> +inline _LIBCPP_INLINE_VISIBILITY +auto +to_address(const _Pointer& __p) _NOEXCEPT +{ + return _VSTD::__to_raw_pointer(__p); +} +#endif template <class _Tp, class = void> struct __has_size_type : false_type {}; diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp new file mode 100644 index 00000000000..64a5c73affe --- /dev/null +++ b/libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <memory> + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// template <class T> constexpr T* to_address(T* p) noexcept; +// template <class Ptr> auto to_address(const Ptr& p) noexcept; + +#include <memory> +#include <cassert> +#include "test_macros.h" + +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(); } +}; +} + +int n = 0; +static_assert(std::to_address(&n) == &n); + +int main() +{ + int i = 0; + ASSERT_NOEXCEPT(std::to_address(&i)); + assert(std::to_address(&i) == &i); + P1 p1(&i); + ASSERT_NOEXCEPT(std::to_address(p1)); + assert(std::to_address(p1) == &i); + P2 p2(&i); + ASSERT_NOEXCEPT(std::to_address(p2)); + assert(std::to_address(p2) == &i); + P3 p3(&i); + ASSERT_NOEXCEPT(std::to_address(p3)); + assert(std::to_address(p3) == &i); + P4 p4(&i); + ASSERT_NOEXCEPT(std::to_address(p4)); + assert(std::to_address(p4) == &i); +} |