File: forwarding-reference-overload.cpp

package info (click to toggle)
llvm-toolchain-17 1%3A17.0.6-22
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,799,624 kB
  • sloc: cpp: 6,428,607; ansic: 1,383,196; asm: 793,408; python: 223,504; objc: 75,364; f90: 60,502; lisp: 33,869; pascal: 15,282; sh: 9,684; perl: 7,453; ml: 4,937; awk: 3,523; makefile: 2,889; javascript: 2,149; xml: 888; fortran: 619; cs: 573
file content (253 lines) | stat: -rw-r--r-- 9,289 bytes parent folder | download | duplicates (5)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t

namespace std {
template <bool B, class T = void> struct enable_if { typedef T type; };

template <class T> struct enable_if<true, T> { typedef T type; };

template <bool B, class T = void>
using enable_if_t = typename enable_if<B, T>::type;

template <class T> struct enable_if_nice { typedef T type; };
} // namespace std

namespace foo {
template <class T> struct enable_if { typedef T type; };
} // namespace foo

template <typename T> constexpr bool just_true = true;

class Test1 {
public:
  template <typename T> Test1(T &&n);
  // CHECK-NOTES: [[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors [bugprone-forwarding-reference-overload]
  // CHECK-NOTES: 48:3: note: copy constructor declared here
  // CHECK-NOTES: 49:3: note: copy constructor declared here
  // CHECK-NOTES: 50:3: note: move constructor declared here

  template <typename T> Test1(T &&n, int i = 5, ...);
  // CHECK-NOTES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors
  // CHECK-NOTES: 48:3: note: copy constructor declared here
  // CHECK-NOTES: 49:3: note: copy constructor declared here
  // CHECK-NOTES: 50:3: note: move constructor declared here

  template <typename T, typename U = typename std::enable_if_nice<T>::type>
  Test1(T &&n);
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
  // CHECK-NOTES: 48:3: note: copy constructor declared here
  // CHECK-NOTES: 49:3: note: copy constructor declared here
  // CHECK-NOTES: 50:3: note: move constructor declared here

  template <typename T>
  Test1(T &&n, typename foo::enable_if<long>::type i = 5, ...);
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
  // CHECK-NOTES: 48:3: note: copy constructor declared here
  // CHECK-NOTES: 49:3: note: copy constructor declared here
  // CHECK-NOTES: 50:3: note: move constructor declared here

  Test1(const Test1 &other) {}
  Test1(Test1 &other) {}
  Test1(Test1 &&other) {}
};

template <typename U> class Test2 {
public:
  // Two parameters without default value, can't act as copy / move constructor.
  template <typename T, class V> Test2(T &&n, V &&m, int i = 5, ...);

  // Guarded with enable_if.
  template <typename T>
  Test2(T &&n, int i = 5,
        std::enable_if_t<sizeof(int) < sizeof(long), int> a = 5, ...);

  // Guarded with enable_if.
  template <typename T, typename X = typename std::enable_if<
                            sizeof(int) < sizeof(long), double>::type &>
  Test2(T &&n);

  // Guarded with enable_if.
  template <typename T>
  Test2(T &&n, typename std::enable_if<just_true<T>>::type **a = nullptr);

  // Guarded with enable_if.
  template <typename T, typename X = std::enable_if_t<just_true<T>> *&&>
  Test2(T &&n, double d = 0.0);

  // Not a forwarding reference parameter.
  template <typename T> Test2(const T &&n);

  // Not a forwarding reference parameter.
  Test2(int &&x);

  // Two parameters without default value, can't act as copy / move constructor.
  template <typename T> Test2(T &&n, int x);

  // Not a forwarding reference parameter.
  template <typename T> Test2(U &&n);
};

// The copy and move constructors are both disabled.
class Test3 {
public:
  template <typename T> Test3(T &&n);

  template <typename T> Test3(T &&n, int I = 5, ...);

  Test3(const Test3 &rhs) = delete;

private:
  Test3(Test3 &&rhs);
};

// Both the copy and the (compiler generated) move constructors can be hidden.
class Test4 {
public:
  template <typename T> Test4(T &&n);
  // CHECK-NOTES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the copy and move constructors

  Test4(const Test4 &rhs);
  // CHECK-NOTES: :[[@LINE-1]]:3: note: copy constructor declared here
};

// Nothing can be hidden, the copy constructor is implicitly deleted.
class Test5 {
public:
  template <typename T> Test5(T &&n);

  Test5(Test5 &&rhs) = delete;
};

// Only the move constructor can be hidden.
class Test6 {
public:
  template <typename T> Test6(T &&n);
  // CHECK-NOTES: :[[@LINE-1]]:25: warning: constructor accepting a forwarding reference can hide the move constructor

  Test6(Test6 &&rhs);
  // CHECK-NOTES: :[[@LINE-1]]:3: note: move constructor declared here
private:
  Test6(const Test6 &rhs);
};

// Do not dereference a null BaseType.
template <class _Callable> class result_of;
template <class _Fp, class ..._Args> class result_of<_Fp(_Args...)> { };
template <class _Tp> using result_of_t = typename result_of<_Tp>::type;

template <class... _Types> struct __overload;
template <class _Tp, class... _Types>
struct __overload<_Tp, _Types...> : __overload<_Types...> {
  using __overload<_Types...>::operator();
};

template <class _Tp, class... _Types>
using __best_match_t = typename result_of_t<__overload<_Types...>(_Tp&&)>::type;

template <class... _Types>
class variant {
public:
  template <class _Arg, class _Tp = __best_match_t<_Arg, _Types...> >
  constexpr variant(_Arg&& __arg) {}
  // CHECK-NOTES: :[[@LINE-1]]:13: warning: constructor accepting a forwarding reference can hide the copy and move constructors
};

namespace std {
template <class T, class U> struct is_same { static constexpr bool value = false; };
template <class T> struct is_same<T, T> { static constexpr bool value = true; };
template <class T, class U> constexpr bool is_same_v = is_same<T, U>::value;
template <class T> struct remove_reference { using type = T; };
template <class T> struct remove_reference<T&> { using type = T; };
template <class T> struct remove_reference<T&&> { using type = T; };
template <class T> using remove_reference_t = typename remove_reference<T>::type;
template <class T> struct remove_cv { using type = T; };
template <class T> struct remove_cv<const T> { using type = T; };
template <class T> struct remove_cv<volatile T> { using type = T; };
template <class T> struct remove_cv<const volatile T> { using type = T; };
template <class T> using remove_cv_t = typename remove_cv<T>::type;
template <class T> struct remove_cvref { using type = remove_cv_t<remove_reference_t<T>>; };
template <class T> using remove_cvref_t = typename remove_cvref<T>::type;
} // namespace std

// Handle enable_if when used as a non-type template parameter.
class Test7 {
public:
  // Guarded with enable_if.
  template <class T,
    typename std::enable_if_t<std::is_same_v<std::remove_cvref_t<T>, int>, int>::type = 0>
  Test7(T &&t);

  // Guarded with enable_if.
  template <class T,
    std::enable_if_t<
      !std::is_same_v<std::remove_cvref_t<T>, Test7>
      && !std::is_same_v<std::remove_cvref_t<T>, bool>, int> = true>
  Test7(T &&t);

  Test7(const Test7 &other) = default;
  Test7(Test7 &&other) = default;
};

// Handle enable_if when used as a non-type template parameter following
// a variadic template parameter pack.
class Test8 {
public:
  // Guarded with enable_if.
  template <class T, class... A,
    std::enable_if_t<
      !std::is_same_v<std::remove_cvref_t<T>, Test8>
      || (sizeof...(A) > 0)>* = nullptr>
  Test8(T &&t, A &&... a);

  Test8(const Test8 &other) = default;
  Test8(Test8 &&other) = default;
};

// Non-type template parameter failure cases.
class Test9 {
public:
  // Requires a default argument (such as a literal, implicit cast expression, etc.)
  template <class T,
    std::enable_if_t<std::is_same_v<std::remove_cvref_t<T>, bool>, int>>
  Test9(T &&t);
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
  // CHECK-NOTES: 240:3: note: copy constructor declared here
  // CHECK-NOTES: 241:3: note: move constructor declared here

  // Requires a default argument (such as a literal, implicit cast expression, etc.)
  template <class T,
    std::enable_if_t<std::is_same_v<std::remove_cvref_t<T>, long>>*>
  Test9(T &&t);
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
  // CHECK-NOTES: 240:3: note: copy constructor declared here
  // CHECK-NOTES: 241:3: note: move constructor declared here

  // Only std::enable_if or std::enable_if_t are supported
  template <class T,
    typename std::enable_if_nice<T>::type* = nullptr>
  Test9(T &&t);
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
  // CHECK-NOTES: 240:3: note: copy constructor declared here
  // CHECK-NOTES: 241:3: note: move constructor declared here

  // Only std::enable_if or std::enable_if_t are supported
  template <class T,
    typename foo::enable_if<T>::type = 0>
  Test9(T &&t);
  // CHECK-NOTES: :[[@LINE-1]]:3: warning: constructor accepting a forwarding reference can hide the copy and move constructors
  // CHECK-NOTES: 240:3: note: copy constructor declared here
  // CHECK-NOTES: 241:3: note: move constructor declared here

  Test9(const Test9 &other) = default;
  Test9(Test9 &&other) = default;
};


template <typename T>
class Test10 {
public:
  enum E {};
  E e;

  Test10(T &&Item, E e)
      : e(e){}
};