1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <memory>
10 
11 // UNSUPPORTED: c++03, c++11, c++14, c++17
12 
13 // template <class T> constexpr T* to_address(T* p) noexcept;
14 // template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
15 
16 #include <memory>
17 #include <cassert>
18 #include "test_macros.h"
19 
20 class P1
21 {
22 public:
23     using element_type = int;
24 
25     constexpr explicit P1(int* p)
26     : p_(p) { }
27 
28     constexpr int* operator->() const noexcept
29     { return p_; }
30 
31 private:
32     int* p_;
33 };
34 
35 class P2
36 {
37 public:
38     using element_type = int;
39 
40     constexpr explicit P2(int* p)
41     : p_(p) { }
42 
43     constexpr P1 operator->() const noexcept
44     { return p_; }
45 
46 private:
47     P1 p_;
48 };
49 
50 class P3
51 {
52 public:
53     constexpr explicit P3(int* p)
54     : p_(p) { }
55 
56     constexpr int* get() const noexcept
57     { return p_; }
58 
59 private:
60     int* p_;
61 };
62 
63 namespace std
64 {
65 template<>
66 struct pointer_traits<::P3>
67 {
68     static constexpr int* to_address(const ::P3& p) noexcept
69     { return p.get(); }
70 };
71 }
72 
73 class P4
74 {
75 public:
76     constexpr explicit P4(int* p)
77     : p_(p) { }
78 
79     constexpr int* operator->() const noexcept
80     { return nullptr; }
81 
82     constexpr int* get() const noexcept
83     { return p_; }
84 
85 private:
86     int* p_;
87 };
88 
89 namespace std
90 {
91 template<>
92 struct pointer_traits<::P4>
93 {
94     constexpr static int* to_address(const ::P4& p) noexcept
95     { return p.get(); }
96 };
97 }
98 
99 int n = 0;
100 static_assert(std::to_address(&n) == &n);
101 
102 constexpr bool test() {
103   int i = 0;
104   ASSERT_NOEXCEPT(std::to_address(&i));
105   assert(std::to_address(&i) == &i);
106   P1 p1(&i);
107   ASSERT_NOEXCEPT(std::to_address(p1));
108   assert(std::to_address(p1) == &i);
109   P2 p2(&i);
110   ASSERT_NOEXCEPT(std::to_address(p2));
111   assert(std::to_address(p2) == &i);
112   P3 p3(&i);
113   ASSERT_NOEXCEPT(std::to_address(p3));
114   assert(std::to_address(p3) == &i);
115   P4 p4(&i);
116   ASSERT_NOEXCEPT(std::to_address(p4));
117   assert(std::to_address(p4) == &i);
118 
119   return true;
120 }
121 
122 int main(int, char**) {
123   test();
124   static_assert(test());
125   return 0;
126 }
127