Home | History | Annotate | Line # | Download | only in experimental
functional revision 1.1
      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
    441