Nugget
functional_base.h
1 // Copyright (c) Electronic Arts Inc. All rights reserved.
4 
5 
6 #ifndef EASTL_INTERNAL_FUNCTIONAL_BASE_H
7 #define EASTL_INTERNAL_FUNCTIONAL_BASE_H
8 
9 #include <EASTL/internal/config.h>
10 
11 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
12  #pragma once
13 #endif
14 
15 #include <EASTL/internal/memory_base.h>
16 #include <EASTL/internal/move_help.h>
17 #include <EASTL/type_traits.h>
18 
19 
20 namespace eastl
21 {
22  // foward declaration for swap
23  template <typename T>
24  inline void swap(T& a, T& b)
26 
27 
43  template <typename R, typename C, typename T, typename... Args>
44  EA_CONSTEXPR auto invoke_impl(R C::*func, T&& obj, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR((eastl::forward<T>(obj).*func)(eastl::forward<Args>(args)...)))
45  -> typename enable_if<is_base_of<C, decay_t<T>>::value,
46  decltype((eastl::forward<T>(obj).*func)(eastl::forward<Args>(args)...))>::type
47  {
48  return (eastl::forward<T>(obj).*func)(eastl::forward<Args>(args)...);
49  }
50 
51  template <typename F, typename... Args>
52  EA_CONSTEXPR auto invoke_impl(F&& func, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(eastl::forward<F>(func)(eastl::forward<Args>(args)...)))
53  -> decltype(eastl::forward<F>(func)(eastl::forward<Args>(args)...))
54  {
55  return eastl::forward<F>(func)(eastl::forward<Args>(args)...);
56  }
57 
58 
59  template <typename R, typename C, typename T, typename... Args>
60  EA_CONSTEXPR auto invoke_impl(R C::*func, T&& obj, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(((*eastl::forward<T>(obj)).*func)(eastl::forward<Args>(args)...)))
61  -> decltype(((*eastl::forward<T>(obj)).*func)(eastl::forward<Args>(args)...))
62  {
63  return ((*eastl::forward<T>(obj)).*func)(eastl::forward<Args>(args)...);
64  }
65 
66  template <typename M, typename C, typename T>
67  EA_CONSTEXPR auto invoke_impl(M C::*member, T&& obj) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(eastl::forward<T>(obj).*member))
68  -> typename enable_if<
69  is_base_of<C, decay_t<T>>::value,
70  decltype(eastl::forward<T>(obj).*member)
71  >::type
72  {
73  return eastl::forward<T>(obj).*member;
74  }
75 
76  template <typename M, typename C, typename T>
77  EA_CONSTEXPR auto invoke_impl(M C::*member, T&& obj) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR((*eastl::forward<T>(obj)).*member))
78  -> decltype((*eastl::forward<T>(obj)).*member)
79  {
80  return (*eastl::forward<T>(obj)).*member;
81  }
82 
83  template <typename F, typename... Args>
84  EA_CONSTEXPR decltype(auto) invoke(F&& func, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(invoke_impl(eastl::forward<F>(func), eastl::forward<Args>(args)...)))
85  {
86  return invoke_impl(eastl::forward<F>(func), eastl::forward<Args>(args)...);
87  }
88 
89  template <typename F, typename = void, typename... Args>
91  };
92 
93  template <typename F, typename... Args>
94  struct invoke_result_impl<F, void_t<decltype(invoke_impl(eastl::declval<F>(), eastl::declval<Args>()...))>, Args...>
95  {
96  typedef decltype(invoke_impl(eastl::declval<F>(), eastl::declval<Args>()...)) type;
97  };
98 
99  template <typename F, typename... Args>
100  struct invoke_result : public invoke_result_impl<F, void, Args...> {};
101 
102  #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
103  template <typename F, typename... Args>
104  using invoke_result_t = typename invoke_result<F, Args...>::type;
105  #endif
106 
107  template <typename F, typename = void, typename... Args>
109 
110  template <typename F, typename... Args>
111  struct is_invocable_impl<F, void_t<typename eastl::invoke_result<F, Args...>::type>, Args...> : public eastl::true_type {};
112 
113  template <typename F, typename... Args>
114  struct is_invocable : public is_invocable_impl<F, void, Args...> {};
115 
116  template <typename R, typename F, typename = void, typename... Args>
118 
119  template <typename R, typename F, typename... Args>
120  struct is_invocable_r_impl<R, F, void_t<typename invoke_result<F, Args...>::type>, Args...>
121  : public is_convertible<typename invoke_result<F, Args...>::type, R> {};
122 
123  template <typename R, typename F, typename... Args>
124  struct is_invocable_r : public is_invocable_r_impl<R, F, void, Args...> {};
125 
126  template <typename F, typename... Args>
127  EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_invocable_v = is_invocable<F, Args...>::value;
128 
129  template <typename R, typename F, typename... Args>
130  EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_invocable_r_v = is_invocable_r<R, F, Args...>::value;
131 
132  template <typename F, typename = void, typename... Args>
134 
135  template <typename F, typename... Args>
136  struct is_nothrow_invocable_impl<F, void_t<typename eastl::invoke_result<F, Args...>::type>, Args...>
137  : public eastl::bool_constant<EA_NOEXCEPT_EXPR(eastl::invoke(eastl::declval<F>(), eastl::declval<Args>()...))> {};
138 
139  template <typename F, typename... Args>
140  struct is_nothrow_invocable : public is_nothrow_invocable_impl<F, void, Args...> {};
141 
142  template <typename R, typename F, typename = void, typename... Args>
144 
145  template <typename R, typename F, typename... Args>
146  struct is_nothrow_invocable_r_impl<R, F, void_t<typename eastl::invoke_result<F, Args...>::type>, Args...>
147  {
148  static EA_CONSTEXPR_OR_CONST bool value = eastl::is_convertible<typename eastl::invoke_result<F, Args...>::type, R>::value
149  && eastl::is_nothrow_invocable<F, Args...>::value;
150  };
151 
152  template <typename R, typename F, typename... Args>
153  struct is_nothrow_invocable_r : public is_nothrow_invocable_r_impl<R, F, void, Args...> {};
154 
155  template <typename F, typename... Args>
156  EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_no_throw_invocable_v = is_nothrow_invocable<F, Args...>::value;
157 
158  template <typename R, typename F, typename... Args>
159  EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, F, Args...>::value;
160 
169  {};
170 
171 
179  EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR allocator_arg_t allocator_arg = allocator_arg_t();
180 
181 
182  template <typename Argument, typename Result>
184  {
185  typedef Argument argument_type;
186  typedef Result result_type;
187  };
188 
189 
190  template <typename Argument1, typename Argument2, typename Result>
192  {
193  typedef Argument1 first_argument_type;
194  typedef Argument2 second_argument_type;
195  typedef Result result_type;
196  };
197 
198 
200  template <typename T = void>
201  struct less : public binary_function<T, T, bool>
202  {
203  EA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const
204  { return a < b; }
205  };
206 
207  // http://en.cppreference.com/w/cpp/utility/functional/less_void
208  template <>
209  struct less<void>
210  {
211  template<typename A, typename B>
212  EA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const
213  -> decltype(eastl::forward<A>(a) < eastl::forward<B>(b))
214  { return eastl::forward<A>(a) < eastl::forward<B>(b); }
215  };
216 
217 
219  template <typename T>
221  {
222  public:
223  typedef T type;
224 
225  reference_wrapper(T&) EA_NOEXCEPT;
226  reference_wrapper(T&&) = delete;
227  reference_wrapper(const reference_wrapper<T>& x) EA_NOEXCEPT;
228 
229  reference_wrapper& operator=(const reference_wrapper<T>& x) EA_NOEXCEPT;
230 
231  operator T& () const EA_NOEXCEPT;
232  T& get() const EA_NOEXCEPT;
233 
234  template <typename... ArgTypes>
235  typename eastl::result_of<T&(ArgTypes&&...)>::type operator() (ArgTypes&&...) const;
236 
237  private:
238  T* val;
239  };
240 
241  template <typename T>
243  : val(eastl::addressof(v))
244  {}
245 
246  template <typename T>
247  reference_wrapper<T>::reference_wrapper(const reference_wrapper<T>& other) EA_NOEXCEPT
248  : val(other.val)
249  {}
250 
251  template <typename T>
252  reference_wrapper<T>& reference_wrapper<T>::operator=(const reference_wrapper<T>& other) EA_NOEXCEPT
253  {
254  val = other.val;
255  return *this;
256  }
257 
258  template <typename T>
259  reference_wrapper<T>::operator T&() const EA_NOEXCEPT
260  {
261  return *val;
262  }
263 
264  template <typename T>
265  T& reference_wrapper<T>::get() const EA_NOEXCEPT
266  {
267  return *val;
268  }
269 
270  template <typename T>
271  template <typename... ArgTypes>
272  typename eastl::result_of<T&(ArgTypes&&...)>::type reference_wrapper<T>::operator() (ArgTypes&&... args) const
273  {
274  return eastl::invoke(*val, eastl::forward<ArgTypes>(args)...);
275  }
276 
277  // reference_wrapper-specific utilties
278  template <typename T>
279  reference_wrapper<T> ref(T& t) EA_NOEXCEPT
280  {
281  return eastl::reference_wrapper<T>(t);
282  }
283 
284  template <typename T>
285  void ref(const T&&) = delete;
286 
287  template <typename T>
288  reference_wrapper<T> ref(reference_wrapper<T>t) EA_NOEXCEPT
289  {
290  return eastl::ref(t.get());
291  }
292 
293  template <typename T>
294  reference_wrapper<const T> cref(const T& t) EA_NOEXCEPT
295  {
297  }
298 
299  template <typename T>
300  void cref(const T&&) = delete;
301 
302  template <typename T>
303  reference_wrapper<const T> cref(reference_wrapper<T> t) EA_NOEXCEPT
304  {
305  return eastl::cref(t.get());
306  }
307 
308 
309  // reference_wrapper-specific type traits
310  template <typename T>
312  : public eastl::false_type {};
313 
314  template <typename T>
316  : public eastl::true_type {};
317 
318  template <typename T>
320  : public eastl::is_reference_wrapper_helper<typename eastl::remove_cv<T>::type> {};
321 
322 
323  // Helper which adds a reference to a type when given a reference_wrapper of that type.
324  template <typename T>
326  { typedef T type; };
327 
328  template <typename T>
330  { typedef T& type; };
331 
332  template <typename T>
334  { typedef T& type; };
335 
336  // reference_wrapper specializations of invoke
337  // These have to come after reference_wrapper is defined, but reference_wrapper needs to have a
338  // definition of invoke, so these specializations need to come after everything else has been defined.
339  template <typename R, typename C, typename T, typename... Args>
340  EA_CONSTEXPR auto invoke_impl(R C::*func, T&& obj, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR((obj.get().*func)(eastl::forward<Args>(args)...)))
342  decltype((obj.get().*func)(eastl::forward<Args>(args)...))>::type
343  {
344  return (obj.get().*func)(eastl::forward<Args>(args)...);
345  }
346 
347  template <typename M, typename C, typename T>
348  EA_CONSTEXPR auto invoke_impl(M C::*member, T&& obj) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(obj.get().*member))
349  -> typename enable_if<is_reference_wrapper<eastl::decay_t<T>>::value,
350  decltype(obj.get().*member)>::type
351  {
352  return obj.get().*member;
353  }
354 
355 
357  // bind
359 
362  template <typename Operation>
363  class binder1st : public unary_function<typename Operation::second_argument_type, typename Operation::result_type>
364  {
365  protected:
366  typename Operation::first_argument_type value;
367  Operation op;
368 
369  public:
370  binder1st(const Operation& x, const typename Operation::first_argument_type& y)
371  : value(y), op(x) { }
372 
373  typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const
374  { return op(value, x); }
375 
376  typename Operation::result_type operator()(typename Operation::second_argument_type& x) const
377  { return op(value, x); }
378  };
379 
380 
381  template <typename Operation, typename T>
382  inline binder1st<Operation> bind1st(const Operation& op, const T& x)
383  {
384  typedef typename Operation::first_argument_type value;
385  return binder1st<Operation>(op, value(x));
386  }
387 
388 
391  template <typename Operation>
392  class binder2nd : public unary_function<typename Operation::first_argument_type, typename Operation::result_type>
393  {
394  protected:
395  Operation op;
396  typename Operation::second_argument_type value;
397 
398  public:
399  binder2nd(const Operation& x, const typename Operation::second_argument_type& y)
400  : op(x), value(y) { }
401 
402  typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const
403  { return op(x, value); }
404 
405  typename Operation::result_type operator()(typename Operation::first_argument_type& x) const
406  { return op(x, value); }
407  };
408 
409 
410  template <typename Operation, typename T>
411  inline binder2nd<Operation> bind2nd(const Operation& op, const T& x)
412  {
413  typedef typename Operation::second_argument_type value;
414  return binder2nd<Operation>(op, value(x));
415  }
416 
417 } // namespace eastl
418 
419 #endif // EASTL_INTERNAL_FUNCTIONAL_BASE_H
Definition: functional_base.h:393
reference_wrapper
Definition: functional_base.h:221
EA Standard Template Library.
Definition: algorithm.h:288
EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR allocator_arg_t allocator_arg
Definition: functional_base.h:179
EA_CONSTEXPR auto invoke_impl(R C::*func, T &&obj, Args &&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR((obj.get().*func)(eastl binder1st< Operation > bind1st(const Operation &op, const T &x)
Definition: functional_base.h:382
T * addressof(T &value) EA_NOEXCEPT
Definition: memory_base.h:29
void swap(T &a, T &b) EA_NOEXCEPT_IF(eastl EA_CONSTEXPR auto invoke_impl(R C::*func, T &&obj, Args &&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR((eastl
Definition: functional_base.h:44
Definition: TestEABase.cpp:2829
Definition: functional_base.h:169
Definition: functional_base.h:192
Definition: type_traits.h:442
Definition: type_traits.h:263
Definition: functional_base.h:90
Definition: functional_base.h:100
Definition: type_compound.h:328
Definition: functional_base.h:108
Definition: functional_base.h:117
Definition: functional_base.h:124
Definition: functional_base.h:114
Definition: functional_base.h:133
Definition: functional_base.h:143
Definition: functional_base.h:153
Definition: functional_base.h:140
Definition: type_pod.h:1676
Definition: type_pod.h:1934
Definition: functional_base.h:312
Definition: functional_base.h:320
less<T>
Definition: functional_base.h:202
Definition: functional_base.h:326
Definition: type_properties.h:359
Definition: functional_base.h:184