38 #ifndef NVWA_FUNCTIONAL_H 39 #define NVWA_FUNCTIONAL_H 47 #include <type_traits> 58 template <
class _T1,
class _T2>
61 struct good {
char dummy; };
62 struct bad {
char dummy[2]; };
63 template <
class _Up,
void (_Up::*)(
size_t)>
struct _SFINAE1 {};
64 template <
class _Up,
size_t (_Up::*)() const>
struct _SFINAE2 {};
65 template <
class _Up>
static good reserve(_SFINAE1<_Up, &_Up::reserve>*);
66 template <
class _Up>
static bad reserve(...);
67 template <
class _Up>
static good size(_SFINAE2<_Up, &_Up::size>*);
68 template <
class _Up>
static bad size(...);
69 static const bool value =
70 (
sizeof(reserve<_T1>(
nullptr)) ==
sizeof(good) &&
71 sizeof(size<_T2>(
nullptr)) ==
sizeof(good));
75 template <
class _T1,
class _T2>
76 void try_reserve(_T1&,
const _T2&, std::false_type)
81 template <
class _T1,
class _T2>
82 void try_reserve(_T1& dest,
const _T2& src, std::true_type)
84 dest.reserve(src.size());
89 template <
typename _Fn,
class _Tuple, std::size_t... _I>
90 constexpr
auto tuple_fmap_impl(_Fn&& f, _Tuple&& t,
91 std::index_sequence<_I...>)
93 return std::make_tuple(f(std::get<_I>(std::forward<_Tuple>(t)))...);
98 template <
typename _Rs,
typename _Fn,
class _Tuple>
99 constexpr _Rs tuple_reduce_impl(_Fn&&, _Rs&& value, _Tuple&&,
100 std::index_sequence<>)
102 return std::forward<_Rs>(value);
107 template <
typename _Rs,
typename _Fn,
class _Tuple, std::size_t _I,
109 constexpr _Rs tuple_reduce_impl(_Fn&& f, _Rs&& value, _Tuple&& t,
110 std::index_sequence<_I, _J...>)
112 return tuple_reduce_impl(std::forward<_Fn>(f),
113 f(std::forward<_Rs>(value), std::get<_I>(t)),
114 std::forward<_Tuple>(t),
115 std::index_sequence<_J...>());
120 template <
typename _Fn,
class _Tuple, std::size_t... _I>
121 constexpr decltype(
auto) tuple_apply_impl(_Fn&& f, _Tuple&& t,
122 std::index_sequence<_I...>)
124 return f(std::get<_I>(std::forward<_Tuple>(t))...);
128 template <
typename _Fn>
131 std::function<_Fn(self_ref_func)> fn;
135 template <
typename _Tp,
136 bool _Deep_copy = std::is_rvalue_reference<_Tp>{} ||
137 (std::is_lvalue_reference<_Tp>{} &&
138 std::is_const<std::remove_reference_t<_Tp>>{})>
141 safe_wrapper(_Tp&& x) : value(std::forward<_Tp>(x)) {}
142 _Tp
get()
const {
return value; }
147 template <
typename _Tp>
148 struct safe_wrapper<_Tp, true>
150 safe_wrapper(_Tp&& x) : value(std::forward<_Tp>(x)) {}
151 template <
typename _Up = _Tp>
152 std::enable_if_t<std::is_rvalue_reference<_Up>{}, std::decay_t<_Tp>>
157 template <
typename _Up = _Tp>
158 std::enable_if_t<!std::is_rvalue_reference<_Up>{}, _Tp>
163 std::decay_t<_Tp> value;
168 template <
typename _Fn>
172 template <
typename _Rs,
typename _Tp>
173 struct curry<std::function<_Rs(_Tp)>>
175 typedef std::function<_Rs(_Tp)> type;
177 static type make(type f)
184 template <
typename _Rs,
typename _Tp,
typename... _Targs>
185 struct curry<std::function<_Rs(_Tp, _Targs...)>>
187 typedef typename curry<std::function<_Rs(_Targs...)>>::type remaining_type;
188 typedef std::function<remaining_type(_Tp)> type;
190 static type make(std::function<_Rs(_Tp, _Targs...)> f)
194 return curry<std::function<_Rs(_Targs...)>>::make(
195 [f, w = safe_wrapper<_Tp>(std::forward<_Tp>(x))](
196 _Targs&&... args) -> decltype(
auto)
198 return f(w.get(), std::forward<_Targs>(args)...);
208 template <
class _Rng>
209 auto adl_begin(_Rng&& rng) -> decltype(begin(rng));
210 template <
class _Rng>
211 auto adl_end(_Rng&& rng) -> decltype(end(rng));
214 template <
class _Rng>
215 using value_type =
typename std::iterator_traits<decltype(
216 adl_begin(std::declval<_Rng>()))>::value_type;
221 template <
typename _Tp>
222 void adl_swap(_Tp& lhs, _Tp& rhs) noexcept(noexcept(
swap(lhs, rhs)));
231 : std::logic_error(
"optional has no valid value now") {}
241 template <
typename _Tp>
245 static_assert(std::is_nothrow_destructible<_Tp>::value,
246 "optional type must be nothrow destructible");
248 optional() noexcept : _M_pointer(
nullptr) {}
252 _M_pointer =
new(_M_value) _Tp(*rhs);
254 _M_pointer =
nullptr;
257 std::is_nothrow_move_constructible<_Tp>::value)
260 _M_pointer =
new(_M_value) _Tp(std::move(*rhs));
262 _M_pointer =
nullptr;
266 _M_pointer =
new(_M_value) _Tp(x);
269 std::is_nothrow_move_constructible<_Tp>::value)
271 _M_pointer =
new(_M_value) _Tp(std::move(x));
281 if (has_value() && rhs.has_value())
282 *_M_pointer = *rhs._M_pointer;
291 std::is_nothrow_move_assignable<_Tp>::value &&
292 std::is_nothrow_move_constructible<_Tp>::value)
294 if (has_value() && rhs.has_value())
295 *_M_pointer = std::move(*rhs._M_pointer);
304 constexpr _Tp* operator->()
308 constexpr
const _Tp* operator->()
const 312 constexpr _Tp& operator*() &
316 constexpr
const _Tp& operator*()
const&
320 constexpr _Tp&& operator*() &&
322 return std::move(*_M_pointer);
325 bool has_value()
const noexcept {
return _M_pointer !=
nullptr; }
333 const _Tp& value()
const&
343 return std::move(*_M_pointer);
346 template <
typename _Up>
347 _Tp value_or(_Up&& default_value)
const&
352 return default_value;
354 template <
typename _Up>
355 _Tp value_or(_Up&& default_value) &&
360 return default_value;
363 void reset() noexcept
368 _M_pointer =
nullptr;
372 std::is_nothrow_move_constructible<_Tp>::value &&
373 noexcept(detail::adl_swap(std::declval<_Tp&>(),
374 std::declval<_Tp&>())))
380 swap(*_M_pointer, *rhs);
384 new (rhs._M_value) _Tp(std::move(*_M_pointer));
392 _M_pointer =
new(_M_value) _Tp(std::move(*rhs));
397 template <
typename... _Targs>
398 void emplace(_Targs&&... args)
401 _M_pointer =
new(_M_value) _Tp(args...);
405 void destroy(_Tp* ptr) noexcept
407 _M_destroy(ptr, std::is_trivially_destructible<_Tp>());
409 void _M_destroy(_Tp*, std::true_type)
411 void _M_destroy(_Tp* ptr, std::false_type)
417 char _M_value[
sizeof(_Tp)];
420 template <
typename _Tp>
426 template <
typename _Tp>
429 return x.has_value();
432 template <
typename _Tp,
typename... _Targs>
436 return first.has_value() && has_value(other...);
439 template <
typename _Tp>
452 template <
typename _Fn>
455 return [f = std::forward<_Fn>(f)](
auto&&... args)
457 typedef std::decay_t<decltype(
458 f(std::forward<decltype(args)>(args).value()...))>
460 if (has_value(args...))
462 f(std::forward<decltype(args)>(args).value()...));
478 template <
typename _Fn,
typename... _Opt>
479 constexpr
auto apply(_Fn&& f, _Opt&&... args) -> decltype(
482 std::decay_t<decltype(f(std::forward<_Opt>(args).value()...))>>())
484 typedef std::decay_t<decltype(f(std::forward<_Opt>(args).value()...))>
486 if (has_value(args...))
488 f(std::forward<_Opt>(args).value()...));
501 template <
typename _Fn,
class _Tuple>
502 constexpr
auto apply(_Fn&& f, _Tuple&& t)
503 -> decltype(detail::tuple_apply_impl(
504 std::forward<_Fn>(f),
505 std::forward<_Tuple>(t),
506 std::make_index_sequence<
507 std::tuple_size<std::decay_t<_Tuple>>::value>()))
509 return detail::tuple_apply_impl(
510 std::forward<_Fn>(f),
511 std::forward<_Tuple>(t),
512 std::make_index_sequence<
513 std::tuple_size<std::decay_t<_Tuple>>::value>());
524 template <
typename _Fn,
typename _T1,
typename _T2>
525 constexpr
auto fmap(_Fn&& f,
const std::pair<_T1, _T2>& args)
527 return std::make_pair(f(args.first), f(args.second));
538 template <
typename _Fn,
typename... _Targs>
539 constexpr
auto fmap(_Fn&& f,
const std::tuple<_Targs...>& args)
541 return detail::tuple_fmap_impl(std::forward<_Fn>(f), args,
542 std::index_sequence_for<_Targs...>());
559 template <
template <
typename,
typename>
class _OutCont = std::vector,
560 template <
typename>
class _Alloc = std::allocator,
561 typename _Fn,
class _Rng>
562 constexpr
auto fmap(_Fn&& f, _Rng&& inputs) -> decltype(
563 detail::adl_begin(inputs), detail::adl_end(inputs),
565 std::decay_t<decltype(f(*detail::adl_begin(inputs)))>,
566 _Alloc<std::decay_t<decltype(f(*detail::adl_begin(inputs)))>>>())
568 typedef std::decay_t<decltype(f(*detail::adl_begin(inputs)))>
570 _OutCont<result_type, _Alloc<result_type>> result;
573 std::integral_constant<
574 bool, detail::can_reserve<decltype(result), _Rng>::value>());
575 for (
auto& item : inputs)
576 result.push_back(f(item));
589 template <
typename _Rs,
typename _Fn,
typename... _Targs>
591 const std::tuple<_Targs...>& args,
594 return detail::tuple_reduce_impl(std::forward<_Fn>(f),
595 std::forward<_Rs>(value),
597 std::index_sequence_for<_Targs...>());
612 template <
typename _Fn,
class _Rng>
613 constexpr
auto reduce(_Fn&& f, _Rng&& inputs)
615 auto result =
typename detail::value_type<_Rng>();
616 for (
auto& item : inputs)
617 result = f(result, item);
637 template <
typename _Rs,
typename _Fn,
typename _Iter>
638 constexpr _Rs&&
reduce(_Fn&& f, _Rs&& value, _Iter begin, _Iter end)
644 return std::forward<_Rs>(value);
645 _Iter current = begin;
646 decltype(
auto) reduced_once = f(std::forward<_Rs>(value), *current);
647 return reduce(std::forward<_Fn>(f), reduced_once, ++begin, end);
675 template <
typename _Rs,
typename _Fn,
class _Rng>
676 constexpr
auto reduce(_Fn&& f, _Rng&& inputs, _Rs&& initval)
677 -> decltype(f(initval, *detail::adl_begin(inputs)))
681 return reduce(std::forward<_Fn>(f), std::forward<_Rs>(initval),
682 begin(inputs), end(inputs));
691 template <
typename _T1,
typename _T2,
typename _Fn>
694 return [f = std::forward<_Fn>(f)](
const std::pair<_T1, _T2>& arg)
697 return f(arg.first, arg.second);
709 template <
typename _Tuple,
typename _Fn>
712 return [f = std::forward<_Fn>(f)](_Tuple&& t) -> decltype(
auto)
714 return apply(f, std::forward<_Tuple>(t));
721 template <
typename _Tp>
724 return std::forward<_Tp>(data);
734 template <
typename _Tp,
typename _Fn,
typename... _Fargs>
735 constexpr decltype(
auto)
pipeline(_Tp&& data, _Fn&& f, _Fargs&&... args)
737 return pipeline(f(std::forward<_Tp>(data)),
738 std::forward<_Fargs>(args)...);
748 return [](
auto&& x) -> decltype(
auto)
750 return std::forward<decltype(x)>(x);
760 template <
typename _Fn>
763 return [f](
auto&&... x) -> decltype(
auto)
765 return f(std::forward<decltype(x)>(x)...);
776 template <
typename _Fn,
typename... _Fargs>
779 return [f, args...](
auto&&... x) -> decltype(
auto)
781 return f(
compose(args...)(std::forward<decltype(x)>(x)...));
792 template <
typename _Rs,
typename _Tp>
794 std::function<_Rs(std::function<_Rs(_Tp)>, _Tp)> f)
798 return f([f](_Tp&& x)
802 std::forward<_Tp>(x));
813 template <
typename _Rs,
typename _Tp>
815 std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)> f)
817 return f([f](_Tp&& x)
830 template <
typename _Rs,
typename _Tp>
832 std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)> f)
834 typedef std::function<_Rs(_Tp)> fn_1st_ord;
835 typedef detail::self_ref_func<fn_1st_ord> fn_self_ref;
840 return f(fn_1st_ord([x](_Tp&& y)
842 return x.fn(x)(std::forward<_Tp>(y));
859 template <
typename _Rs,
typename... _Targs>
862 return detail::curry<std::function<_Rs(_Targs...)>>::make(std::move(f));
875 template <
typename _Rs,
typename... _Targs>
878 return detail::curry<std::function<_Rs(_Targs...)>>::make(f);
892 template <
typename _FnType,
typename _Fn>
895 return detail::curry<std::function<_FnType>>::make(
896 std::forward<_Fn>(f));
901 #endif // NVWA_FUNCTIONAL_H constexpr auto wrap_args_as_pair(_Fn &&f)
Makes a two-argument function accept a pair instead.
Definition: functional.h:692
Class for optional values.
Definition: functional.h:242
void swap(bool_array &lhs, bool_array &rhs) noexcept
Exchanges the content of two bool_arrays.
Definition: bool_array.h:358
constexpr auto fmap(_Fn &&f, _Rng &&inputs) -> decltype(detail::adl_begin(inputs), detail::adl_end(inputs), _OutCont< std::decay_t< decltype(f(*detail::adl_begin(inputs)))>, _Alloc< std::decay_t< decltype(f(*detail::adl_begin(inputs)))>>>())
Applies a function to each element in the input range.
Definition: functional.h:562
std::function< _Rs(_Tp)> fix_curry(std::function< std::function< _Rs(_Tp)>(std::function< _Rs(_Tp)>)> f)
Generates the fixed point using the Curry-style fixed-point combinator.
Definition: functional.h:831
Class for bad optional access exception.
Definition: functional.h:227
constexpr auto reduce(_Fn &&f, _Rng &&inputs, _Rs &&initval) -> decltype(f(initval, *detail::adl_begin(inputs)))
Applies a function cumulatively to elements in the input range.
Definition: functional.h:676
std::function< _Rs(_Tp)> fix_simple(std::function< std::function< _Rs(_Tp)>(std::function< _Rs(_Tp)>)> f)
Generates the fixed point using the simple fixed-point combinator.
Definition: functional.h:814
auto compose(_Fn f, _Fargs... args)
Constructs a function (object) that composes the passed functions.
Definition: functional.h:777
constexpr auto wrap_args_as_tuple(_Fn &&f)
Makes a function accept a tuple as its arguments.
Definition: functional.h:710
decltype(auto) constexpr pipeline(_Tp &&data, _Fn &&f, _Fargs &&... args)
Applies the functions in the arguments to the data consecutively.
Definition: functional.h:735
constexpr auto apply(_Fn &&f, _Tuple &&t) -> decltype(detail::tuple_apply_impl(std::forward< _Fn >(f), std::forward< _Tuple >(t), std::make_index_sequence< std::tuple_size< std::decay_t< _Tuple >>::value >()))
Applies the function with all elements of the typle as arguments.
Definition: functional.h:502
auto make_curry(_Fn &&f)
Makes a curried function.
Definition: functional.h:893
auto lift_optional(_Fn &&f)
Lifts a function so that it takes optionals and returns an optional.
Definition: functional.h:453
Common definitions for preprocessing.