File: lwg3545.cc

package info (click to toggle)
gcc-arm-none-eabi 15%3A14.2.rel1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,099,328 kB
  • sloc: cpp: 3,627,108; ansic: 2,571,498; ada: 834,230; f90: 235,082; makefile: 79,231; asm: 74,984; xml: 51,692; exp: 39,736; sh: 33,298; objc: 15,629; python: 15,069; fortran: 14,429; pascal: 7,003; awk: 5,070; perl: 3,106; ml: 285; lisp: 253; lex: 204; haskell: 135
file content (118 lines) | stat: -rw-r--r-- 3,911 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// { dg-do compile { target c++11 } }

// LWG 3545. std::pointer_traits should be SFINAE-friendly

#include <memory>

using std::is_same;

template<typename> using void_t = void;

template<template<typename> class Probe, typename T, typename = void>
  struct has_member
  : std::false_type { };

template<template<typename> class Probe, typename T>
  struct has_member<Probe, T, void_t<Probe<T>>>
  : std::true_type { };

template<typename T>
  using element_type = typename T::element_type;
template<typename T>
  using pointer = typename T::pointer;
template<typename T>
  using difference_type = typename T::difference_type;
template<typename T>
  using rebind = typename T::template rebind<short>;
template<typename T>
  using pointer_to = decltype(T::pointer_to(std::declval<element_type<T>&>()));

using invalid = std::pointer_traits<int>;
invalid i; // invalid instantiation is not ill-formed

static_assert( !has_member<element_type, invalid>::value, "" );
static_assert( !has_member<pointer, invalid>::value, "" );
static_assert( !has_member<difference_type, invalid>::value, "" );
static_assert( !has_member<rebind, invalid>::value, "" );
static_assert( !has_member<pointer_to, invalid>::value, "" );

struct I
{
  // These members should not be used by pointer_traits<P>::pointer.
  using pointer = int;
  using difference_type = int;
  template<typename> using rebind = int;
};

using invalid2 = std::pointer_traits<I>;

static_assert( !has_member<element_type, invalid2>::value, "" );
static_assert( !has_member<pointer, invalid2>::value, "" );
static_assert( !has_member<difference_type, invalid2>::value, "" );
static_assert( !has_member<rebind, invalid2>::value, "" );
static_assert( !has_member<pointer_to, invalid2>::value, "" );

struct P
{
  using element_type = long;
  struct pointer { }; // should not be used by pointer_traits<P>::pointer

  P pointer_to(long&) const; // not static, should not be used.
};
using Ptraits = std::pointer_traits<P>;
Ptraits p;

static_assert( is_same<element_type<Ptraits>, long>::value, "" );
static_assert( is_same<pointer<Ptraits>, P>::value, "" );
static_assert( is_same<difference_type<Ptraits>, std::ptrdiff_t>::value, "" );
static_assert( !has_member<rebind, Ptraits>::value, "" );
#if __cplusplus >= 202002L
// pointer_traits<P>::pointer_to(long&) is constrained in C++20 and later.
static_assert( !has_member<pointer_to, Ptraits>::value, "" );
#else
static_assert( is_same<pointer_to<Ptraits>, P>::value, "" );
#endif

struct V { using element_type = const void; };
using Vtraits = std::pointer_traits<V>;
Vtraits v;

static_assert( is_same<element_type<Vtraits>, const void>::value, "" );
static_assert( is_same<pointer<Vtraits>, V>::value, "" );
static_assert( is_same<difference_type<Vtraits>, std::ptrdiff_t>::value, "" );
static_assert( !has_member<rebind, Vtraits>::value, "" );
static_assert( !has_member<pointer_to, Vtraits>::value, "" );

template<typename T>
struct clever_ptr
{
  static T obj;

  static clever_ptr pointer_to(T&) { return {}; }
  constexpr T* operator->() const { return &obj; }
};

using Ctraits = std::pointer_traits<clever_ptr<char>>;

static_assert( is_same<element_type<Ctraits>, char>::value, "" );
static_assert( is_same<pointer<Ctraits>, clever_ptr<char>>::value, "" );
static_assert( is_same<difference_type<Ctraits>, std::ptrdiff_t>::value, "" );
static_assert( is_same<rebind<Ctraits>, clever_ptr<short>>::value, "" );
static_assert( is_same<pointer_to<Ctraits>, clever_ptr<char>>::value, "" );

#ifdef __cpp_concepts
struct ptr_base { };

// Program-defined specialization must not be ambiguous with primary template.
template<typename P> requires std::derived_from<P, ptr_base>
struct std::pointer_traits<P>
{
  using element_type = int;
  using difference_type = long;
  using pointer = P;
};

struct Ptr : ptr_base { using element_type = int; };

using E = std::pointer_traits<Ptr>::element_type;
#endif