#ifndef CORE_FUNCTIONAL_HPP #define CORE_FUNCTIONAL_HPP #include #include #include #include #include namespace core { inline namespace v2 { template using is_reference_wrapper = meta::is_specialization_of< remove_cv_t, ::std::reference_wrapper >; template struct function_traits; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits { using typelist = meta::list; using return_type = R; using pointer = add_pointer_t; static constexpr auto arity = typelist::size(); template <::std::size_t N> using argument = meta::get; }; template struct function_traits { using functor_type = function_traits::operator())>; using return_type = typename functor_type::return_type; using pointer = typename functor_type::pointer; static constexpr auto arity = functor_type::arity - 1; template <::std::size_t N> using argument = typename functor_type::template argument; }; /* N3727 */ template auto invoke (Functor&& f, Args&&... args) -> enable_if_t< ::std::is_member_pointer>::value, result_of_t > { return ::std::mem_fn(f)(core::forward(args)...); } template auto invoke (Functor&& f, Args&&... args) -> enable_if_t< not ::std::is_member_pointer>::value, result_of_t > { return core::forward(f)(core::forward(args)...); } template auto apply (F&& f, T&& t, index_sequence) -> decltype( invoke(core::forward(f), ::std::get(core::forward(t))...) ) { return invoke(core::forward(f), ::std::get(core::forward(t))...); } template < class Functor, class T, class I = make_index_sequence<::std::tuple_size>::value> > auto apply (Functor&& f, T&& t) -> decltype( apply(core::forward(f), core::forward(t), I { }) ) { return apply(core::forward(f), core::forward(t), I { }); } template struct apply_functor { template explicit apply_functor (G&& g) : f(core::forward(g)) { } template auto operator () (Applicable&& args) -> decltype( core::apply(core::forward(this->f), core::forward(args)) ) { return apply(core::forward(f), core::forward(args)); } private: F f; }; template auto make_apply (F&& f) -> apply_functor { return apply_functor { core::forward(f) }; } template struct not_fn_functor { template explicit not_fn_functor (G&& g) : f(core::forward(g)) { } template auto operator () (Args&&... args) const -> decltype( not (invoke)(::std::declval(), core::forward(args)...) ) { return not (invoke)(f, core::forward(args)...); } template auto operator () (Args&&... args) -> decltype( not (invoke)(::std::declval(), core::forward(args)...) ) { return not (invoke)(f, core::forward(args)...); } private: F f; }; /* Were this C++14, we could just use a lambda with a capture. Oh Well! */ template not_fn_functor> not_fn (F&& f) { return not_fn_functor> { core::forward(f) }; } /* converter function object */ template struct converter { template constexpr T operator () (Args&&... args) const { return T(core::forward(args)...); } }; /* function objects -- arithmetic */ template struct plus { constexpr T operator () (T const& l, T const& r) const { return l + r; } }; template struct minus { constexpr T operator () (T const& l, T const& r) const { return l - r; } }; template struct multiplies { constexpr T operator () (T const& l, T const& r) const { return l * r; } }; template struct divides { constexpr T operator () (T const& l, T const& r) const { return l / r; } }; template struct modulus { constexpr T operator () (T const& l, T const& r) const { return l % r; } }; template struct negate { constexpr T operator () (T const& arg) const { return -arg; } }; /* function objects -- comparisons */ template struct equal_to { constexpr bool operator () (T const& l, T const& r) const { return l == r; } }; template struct not_equal_to { constexpr bool operator () (T const& l, T const& r) const { return l != r; } }; template struct greater_equal { constexpr bool operator () (T const& l, T const& r) const { return l >= r; } }; template struct less_equal { constexpr bool operator () (T const& l, T const& r) const { return l <= r; } }; template struct greater { constexpr bool operator () (T const& l, T const& r) const { return l > r; } }; template struct less { constexpr bool operator () (T const& l, T const& r) const { return l < r; } }; /* function objects -- logical */ template struct logical_and { constexpr bool operator () (T const& l, T const& r) const { return l and r; } }; template struct logical_or { constexpr bool operator () (T const& l, T const& r) const { return l or r; } }; template struct logical_not { constexpr bool operator () (T const& arg) const { return not arg; } }; /* function objects -- bitwise */ template struct bit_and { constexpr bool operator () (T const& l, T const& r) const { return l & r; } }; template struct bit_or { constexpr bool operator () (T const& l, T const& r) const { return l | r; } }; template struct bit_xor { constexpr bool operator () (T const& l, T const& r) const { return l ^ r; } }; template struct bit_not { constexpr bool operator () (T const& arg) const { return ~arg; } }; /* function objects -- arithmetic specializations */ template <> struct plus { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) + core::forward(u) ) { return core::forward(t) + core::forward(u); } }; template <> struct minus { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) - core::forward(u) ) { return core::forward(t) - core::forward(u); } }; template <> struct multiplies { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) * core::forward(u) ) { return core::forward(t) * core::forward(u); } }; template <> struct divides { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) / core::forward(u) ) { return core::forward(t) / core::forward(u); } }; template <> struct modulus { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) % core::forward(u) ) { return core::forward(t) % core::forward(u); } }; template <> struct negate { using is_transparent = void; template constexpr auto operator () (T&& t) const -> decltype(core::forward(t)) { return core::forward(t); } }; /* function objects -- comparison specialization */ template <> struct equal_to { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) == core::forward(u) ) { return core::forward(t) == core::forward(u); } }; template <> struct not_equal_to { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) != core::forward(u) ) { return core::forward(t) != core::forward(u); } }; template <> struct greater_equal { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) >= core::forward(u) ) { return core::forward(t) >= core::forward(u); } }; template <> struct less_equal { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) <= core::forward(u) ) { return core::forward(t) <= core::forward(u); } }; template <> struct greater { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) > core::forward(u) ) { return core::forward(t) > core::forward(u); } }; template <> struct less { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) < core::forward(u) ) { return core::forward(t) < core::forward(u); } }; /* function objects -- logical specializations */ template <> struct logical_and { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) and core::forward(u) ) { return core::forward(t) and core::forward(u); } }; template <> struct logical_or { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) or core::forward(u) ) { return core::forward(t) or core::forward(u); } }; template <> struct logical_not { using is_transparent = void; template constexpr auto operator () (T&& t) const -> decltype( not core::forward(t) ) { return not core::forward(t); } }; /* function objects -- bitwise specializations */ template <> struct bit_and { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) & core::forward(u) ) { return core::forward(t) & core::forward(u); } }; template <> struct bit_or { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) | core::forward(u) ) { return core::forward(t) | core::forward(u); } }; template <> struct bit_xor { using is_transparent = void; template constexpr auto operator () (T&& t, U&& u) const -> decltype( core::forward(t) ^ core::forward(u) ) { return core::forward(t) ^ core::forward(u); } }; template <> struct bit_not { using is_transparent = void; template constexpr auto operator () (T&& t) const -> decltype(~core::forward(t)) { return ~core::forward(t); } }; /* N3980 Implementation */ }} /* namespace core::v2 */ #endif /* CORE_FUNCTIONAL_HPP */