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 // Test that `std::pointer_traits` is empty when the pointer type has
12 // no element_type typedef. See http://wg21.link/LWG3545 for details.
13 
14 #include <memory>
15 #include <type_traits>
16 #include <utility>
17 
18 #include "test_macros.h"
19 
20 template <typename... Ts>
21 struct VoidifyImpl {
22   using type = void;
23 };
24 
25 template <typename... Ts>
26 using Voidify = typename VoidifyImpl<Ts...>::type;
27 
28 template <class T, class = void>
29 struct HasElementType : std::false_type {};
30 
31 template <class T>
32 struct HasElementType<T, Voidify<typename std::pointer_traits<T>::element_type> > : std::true_type {};
33 
34 template <class T, class = void>
35 struct HasPointerType : std::false_type {};
36 
37 template <class T>
38 struct HasPointerType<T, Voidify<typename std::pointer_traits<T>::pointer> > : std::true_type {};
39 
40 template <class T, class = void>
41 struct HasDifferenceType : std::false_type {};
42 
43 template <class T>
44 struct HasDifferenceType<T, Voidify<typename std::pointer_traits<T>::difference_type> > : std::true_type {};
45 
46 template <class T, class U, class = void>
47 struct HasRebind : std::false_type {};
48 
49 #if TEST_STD_VER >= 11
50 template <class T, class U>
51 struct HasRebind<T, U, Voidify<typename std::pointer_traits<T>::template rebind<U> > > : std::true_type {};
52 #else
53 template <class T, class U>
54 struct HasRebind<T, U, Voidify<typename std::pointer_traits<T>::template rebind<U>::other> > : std::true_type {};
55 #endif
56 
57 template <class T, class = void>
58 struct HasPointerTo : std::false_type {};
59 
60 template <class T>
61 struct HasPointerTo<
62     T,
63     Voidify<decltype(std::pointer_traits<T>::pointer_to(
64         std::declval<typename std::add_lvalue_reference<typename std::pointer_traits<T>::element_type>::type>()))> >
65     : std::true_type {};
66 
67 struct NotAPtr {};
68 
69 static_assert(!HasElementType<NotAPtr>::value, "");
70 static_assert(!HasPointerType<NotAPtr>::value, "");
71 static_assert(!HasDifferenceType<NotAPtr>::value, "");
72 static_assert(!HasRebind<NotAPtr, long>::value, "");
73 static_assert(!HasPointerTo<NotAPtr>::value, "");
74