libstdc++
experimental/functional
Go to the documentation of this file.
1 // <experimental/functional> -*- C++ -*-
2 
3 // Copyright (C) 2014-2015 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file experimental/functional
26  * This is a TS C++ Library header.
27  */
28 
29 #ifndef _GLIBCXX_EXPERIMENTAL_FUNCTIONAL
30 #define _GLIBCXX_EXPERIMENTAL_FUNCTIONAL 1
31 
32 #pragma GCC system_header
33 
34 #if __cplusplus <= 201103L
35 # include <bits/c++14_warning.h>
36 #else
37 
38 #include <functional>
39 #include <tuple>
40 #include <iterator>
41 #include <unordered_map>
42 #include <vector>
43 #include <array>
44 #include <bits/stl_algo.h>
45 
46 namespace std _GLIBCXX_VISIBILITY(default)
47 {
48 namespace experimental
49 {
50 inline namespace fundamentals_v1
51 {
52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
53 
54  // See C++14 ยง20.9.9, Function object binders
55 
56  /// Variable template for std::is_bind_expression
57  template<typename _Tp>
58  constexpr bool is_bind_expression_v = std::is_bind_expression<_Tp>::value;
59 
60  /// Variable template for std::is_placeholder
61  template<typename _Tp>
62  constexpr int is_placeholder_v = std::is_placeholder<_Tp>::value;
63 
64 #define __cpp_lib_experimental_boyer_moore_searching 201411
65 
66  // Searchers
67 
68  template<typename _ForwardIterator1, typename _BinaryPredicate = equal_to<>>
69  class default_searcher
70  {
71  public:
72  default_searcher(_ForwardIterator1 __pat_first,
73  _ForwardIterator1 __pat_last,
74  _BinaryPredicate __pred = _BinaryPredicate())
75  : _M_m(__pat_first, __pat_last, std::move(__pred))
76  { }
77 
78  template<typename _ForwardIterator2>
79  _ForwardIterator2
80  operator()(_ForwardIterator2 __first, _ForwardIterator2 __last) const
81  {
82  return std::search(__first, __last,
83  std::get<0>(_M_m), std::get<1>(_M_m),
84  std::get<2>(_M_m));
85  }
86 
87  private:
88  std::tuple<_ForwardIterator1, _ForwardIterator1, _BinaryPredicate> _M_m;
89  };
90 
91  template<typename _Key, typename _Tp, typename _Hash, typename _Pred>
92  struct __boyer_moore_map_base
93  {
94  template<typename _RAIter>
95  __boyer_moore_map_base(_RAIter __pat, size_t __patlen,
96  _Hash&& __hf, _Pred&& __pred)
97  : _M_bad_char{ __patlen, std::move(__hf), std::move(__pred) }
98  {
99  if (__patlen > 0)
100  for (__diff_type __i = 0; __i < __patlen - 1; ++__i)
101  _M_bad_char[__pat[__i]] = __patlen - 1 - __i;
102  }
103 
104  using __diff_type = _Tp;
105 
106  __diff_type
107  _M_lookup(_Key __key, __diff_type __not_found) const
108  {
109  auto __iter = _M_bad_char.find(__key);
110  if (__iter == _M_bad_char.end())
111  return __not_found;
112  return __iter->second;
113  }
114 
115  _Pred
116  _M_pred() const { return _M_bad_char.key_eq(); }
117 
118  std::unordered_map<_Key, _Tp, _Hash, _Pred> _M_bad_char;
119  };
120 
121  template<typename _Tp, size_t _Len, typename _Pred>
122  struct __boyer_moore_array_base
123  {
124  template<typename _RAIter, typename _Unused>
125  __boyer_moore_array_base(_RAIter __pat, size_t __patlen,
126  _Unused&&, _Pred&& __pred)
127  : _M_bad_char{ {}, std::move(__pred) }
128  {
129  std::get<0>(_M_bad_char).fill(__patlen);
130  if (__patlen > 0)
131  for (__diff_type __i = 0; __i < __patlen - 1; ++__i)
132  {
133  auto __ch = __pat[__i];
134  using _UCh = std::make_unsigned_t<decltype(__ch)>;
135  auto __uch = static_cast<_UCh>(__ch);
136  std::get<0>(_M_bad_char)[__uch] = __patlen - 1 - __i;
137  }
138  }
139 
140  using __diff_type = _Tp;
141 
142  template<typename _Key>
143  __diff_type
144  _M_lookup(_Key __key, __diff_type __not_found) const
145  {
146  auto __ukey = static_cast<std::make_unsigned_t<_Key>>(__key);
147  if (__ukey >= _Len)
148  return __not_found;
149  return std::get<0>(_M_bad_char)[__ukey];
150  }
151 
152  const _Pred&
153  _M_pred() const { return std::get<1>(_M_bad_char); }
154 
155  std::tuple<std::array<_Tp, _Len>, _Pred> _M_bad_char;
156  };
157 
158  template<typename _Pred>
159  struct __is_std_equal_to : std::false_type { };
160 
161  template<>
162  struct __is_std_equal_to<std::equal_to<void>> : std::true_type { };
163 
164  // Use __boyer_moore_array_base when pattern consists of narrow characters
165  // and uses std::equal_to as the predicate.
166  template<typename _RAIter, typename _Hash, typename _Pred,
167  typename _Val = typename iterator_traits<_RAIter>::value_type,
168  typename _Diff = typename iterator_traits<_RAIter>::difference_type>
169  using __boyer_moore_base_t
170  = std::conditional_t<sizeof(_Val) == 1 && is_integral<_Val>::value
171  && __is_std_equal_to<_Pred>::value,
172  __boyer_moore_array_base<_Diff, 256, _Pred>,
173  __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>;
174 
175  template<typename _RAIter, typename _Hash
176  = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
177  typename _BinaryPredicate = std::equal_to<>>
178  class boyer_moore_searcher
179  : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>
180  {
181  using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>;
182  using typename _Base::__diff_type;
183 
184  public:
185  boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last,
186  _Hash __hf = _Hash(),
187  _BinaryPredicate __pred = _BinaryPredicate());
188 
189  template<typename _RandomAccessIterator2>
190  _RandomAccessIterator2
191  operator()(_RandomAccessIterator2 __first,
192  _RandomAccessIterator2 __last) const;
193 
194  private:
195  bool
196  _M_is_prefix(_RAIter __word, __diff_type __len,
197  __diff_type __pos)
198  {
199  const auto& __pred = this->_M_pred();
200  __diff_type __suffixlen = __len - __pos;
201  for (__diff_type __i = 0; __i < __suffixlen; ++__i)
202  if (!__pred(__word[__i], __word[__pos + __i]))
203  return false;
204  return true;
205  }
206 
207  __diff_type
208  _M_suffix_length(_RAIter __word, __diff_type __len,
209  __diff_type __pos)
210  {
211  const auto& __pred = this->_M_pred();
212  __diff_type __i = 0;
213  while (__pred(__word[__pos - __i], __word[__len - 1 - __i])
214  && __i < __pos)
215  {
216  ++__i;
217  }
218  return __i;
219  }
220 
221  template<typename _Tp>
222  __diff_type
223  _M_bad_char_shift(_Tp __c) const
224  { return this->_M_lookup(__c, _M_pat_end - _M_pat); }
225 
226  _RAIter _M_pat;
227  _RAIter _M_pat_end;
228  std::vector<__diff_type> _M_good_suffix;
229  };
230 
231  template<typename _RAIter, typename _Hash
232  = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
233  typename _BinaryPredicate = std::equal_to<>>
234  class boyer_moore_horspool_searcher
235  : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>
236  {
237  using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>;
238  using typename _Base::__diff_type;
239 
240  public:
241  boyer_moore_horspool_searcher(_RAIter __pat,
242  _RAIter __pat_end,
243  _Hash __hf = _Hash(),
244  _BinaryPredicate __pred
245  = _BinaryPredicate())
246  : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)),
247  _M_pat(__pat), _M_pat_end(__pat_end)
248  { }
249 
250  template<typename _RandomAccessIterator2>
251  _RandomAccessIterator2
252  operator()(_RandomAccessIterator2 __first,
253  _RandomAccessIterator2 __last) const
254  {
255  const auto& __pred = this->_M_pred();
256  auto __patlen = _M_pat_end - _M_pat;
257  if (__patlen == 0)
258  return __first;
259  auto __len = __last - __first;
260  while (__len >= __patlen)
261  {
262  for (auto __scan = __patlen - 1;
263  __pred(__first[__scan], _M_pat[__scan]); --__scan)
264  if (__scan == 0)
265  return __first;
266  auto __shift = _M_bad_char_shift(__first[__patlen - 1]);
267  __len -= __shift;
268  __first += __shift;
269  }
270  return __last;
271  }
272 
273  private:
274  template<typename _Tp>
275  __diff_type
276  _M_bad_char_shift(_Tp __c) const
277  { return this->_M_lookup(__c, _M_pat_end - _M_pat); }
278 
279  _RAIter _M_pat;
280  _RAIter _M_pat_end;
281  };
282 
283  /// Generator function for default_searcher
284  template<typename _ForwardIterator,
285  typename _BinaryPredicate = std::equal_to<>>
286  inline default_searcher<_ForwardIterator, _BinaryPredicate>
287  make_default_searcher(_ForwardIterator __pat_first,
288  _ForwardIterator __pat_last,
289  _BinaryPredicate __pred = _BinaryPredicate())
290  { return { __pat_first, __pat_last, __pred }; }
291 
292  /// Generator function for boyer_moore_searcher
293  template<typename _RAIter, typename _Hash
294  = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
295  typename _BinaryPredicate = equal_to<>>
296  inline boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>
297  make_boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last,
298  _Hash __hf = _Hash(),
299  _BinaryPredicate __pred = _BinaryPredicate())
300  { return { __pat_first, __pat_last, std::move(__hf), std::move(__pred) }; }
301 
302  /// Generator function for boyer_moore_horspool_searcher
303  template<typename _RAIter, typename _Hash
304  = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
305  typename _BinaryPredicate = equal_to<>>
306  inline boyer_moore_horspool_searcher<_RAIter, _Hash, _BinaryPredicate>
307  make_boyer_moore_horspool_searcher(_RAIter __pat_first, _RAIter __pat_last,
308  _Hash __hf = _Hash(),
309  _BinaryPredicate __pred
310  = _BinaryPredicate())
311  { return { __pat_first, __pat_last, std::move(__hf), std::move(__pred) }; }
312 
313  template<typename _RAIter, typename _Hash, typename _BinaryPredicate>
314  boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>::
315  boyer_moore_searcher(_RAIter __pat, _RAIter __pat_end,
316  _Hash __hf, _BinaryPredicate __pred)
317  : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)),
318  _M_pat(__pat), _M_pat_end(__pat_end), _M_good_suffix(__pat_end - __pat)
319  {
320  auto __patlen = __pat_end - __pat;
321  if (__patlen == 0)
322  return;
323  __diff_type __last_prefix = __patlen - 1;
324  for (__diff_type __p = __patlen - 1; __p >= 0; --__p)
325  {
326  if (_M_is_prefix(__pat, __patlen, __p + 1))
327  __last_prefix = __p + 1;
328  _M_good_suffix[__p] = __last_prefix + (__patlen - 1 - __p);
329  }
330  for (__diff_type __p = 0; __p < __patlen - 1; ++__p)
331  {
332  auto __slen = _M_suffix_length(__pat, __patlen, __p);
333  auto __pos = __patlen - 1 - __slen;
334  if (!__pred(__pat[__p - __slen], __pat[__pos]))
335  _M_good_suffix[__pos] = __patlen - 1 - __p + __slen;
336  }
337  }
338 
339  template<typename _RAIter, typename _Hash, typename _BinaryPredicate>
340  template<typename _RandomAccessIterator2>
341  _RandomAccessIterator2
342  boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>::
343  operator()(_RandomAccessIterator2 __first,
344  _RandomAccessIterator2 __last) const
345  {
346  auto __patlen = _M_pat_end - _M_pat;
347  if (__patlen == 0)
348  return __first;
349  const auto& __pred = this->_M_pred();
350  __diff_type __i = __patlen - 1;
351  auto __stringlen = __last - __first;
352  while (__i < __stringlen)
353  {
354  __diff_type __j = __patlen - 1;
355  while (__j >= 0 && __pred(__first[__i], _M_pat[__j]))
356  {
357  --__i;
358  --__j;
359  }
360  if (__j < 0)
361  return __first + __i + 1;
362  __i += std::max(_M_bad_char_shift(__first[__i]),
363  _M_good_suffix[__j]);
364  }
365  return __last;
366  }
367 
368 _GLIBCXX_END_NAMESPACE_VERSION
369 } // namespace fundamentals_v1
370 
371 inline namespace fundamentals_v2
372 {
373 _GLIBCXX_BEGIN_NAMESPACE_VERSION
374 
375 #define __cpp_lib_experimental_not_fn 201406
376 
377  /// Generalized negator.
378  template<typename _Fn>
379  class _Not_fn
380  {
381  _Fn _M_fn;
382 
383  public:
384  template<typename _Fn2>
385  explicit
386  _Not_fn(_Fn2&& __fn) : _M_fn(std::forward<_Fn2>(__fn)) { }
387 
388  _Not_fn(const _Not_fn& __fn) = default;
389  _Not_fn(_Not_fn&& __fn) = default;
390  _Not_fn& operator=(const _Not_fn& __fn) = default;
391  _Not_fn& operator=(_Not_fn&& __fn) = default;
392  ~_Not_fn() = default;
393 
394  template<typename... _Args>
395  auto
396  operator()(_Args&&... __args)
397  noexcept(noexcept(!_M_fn(std::forward<_Args>(__args)...)))
398  -> decltype(!_M_fn(std::forward<_Args>(__args)...))
399  { return !_M_fn(std::forward<_Args>(__args)...); }
400 
401  template<typename... _Args>
402  auto
403  operator()(_Args&&... __args) const
404  noexcept(noexcept(!_M_fn(std::forward<_Args>(__args)...)))
405  -> decltype(!_M_fn(std::forward<_Args>(__args)...))
406  { return !_M_fn(std::forward<_Args>(__args)...); }
407 
408  template<typename... _Args>
409  auto
410  operator()(_Args&&... __args) volatile
411  noexcept(noexcept(!_M_fn(std::forward<_Args>(__args)...)))
412  -> decltype(!_M_fn(std::forward<_Args>(__args)...))
413  { return !_M_fn(std::forward<_Args>(__args)...); }
414 
415  template<typename... _Args>
416  auto
417  operator()(_Args&&... __args) const volatile
418  noexcept(noexcept(!_M_fn(std::forward<_Args>(__args)...)))
419  -> decltype(!_M_fn(std::forward<_Args>(__args)...))
420  { return !_M_fn(std::forward<_Args>(__args)...); }
421  };
422 
423  /// [func.not_fn] Function template not_fn
424  template<typename _Fn>
425  inline auto
426  not_fn(_Fn&& __fn)
427  noexcept(std::is_nothrow_constructible<std::decay_t<_Fn>, _Fn&&>::value)
428  {
429  using __maybe_type = _Maybe_wrap_member_pointer<std::decay_t<_Fn>>;
430  return _Not_fn<typename __maybe_type::type>{std::forward<_Fn>(__fn)};
431  }
432 
433 _GLIBCXX_END_NAMESPACE_VERSION
434 } // namespace fundamentals_v2
435 } // namespace experimental
436 } // namespace std
437 
438 #endif // C++14
439 
440 #endif // _GLIBCXX_EXPERIMENTAL_FUNCTIONAL