[libc++] Add bind_front function (P0356R5).
Implementes [[ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0356r5.html | P0356R5 ]]. Adds `bind_front` to `functional`.
Reviewed By: ldionne, #libc, Quuxplusone
Differential Revision: https://reviews.llvm.org/D60368
GitOrigin-RevId: 84a50f5911bf8300cc4bea1f60673ede2145345b
diff --git a/include/functional b/include/functional
index f8565e7..c4830e1 100644
--- a/include/functional
+++ b/include/functional
@@ -2992,61 +2992,107 @@
return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...);
}
-template <class _DecayFunc>
-class _LIBCPP_TEMPLATE_VIS __not_fn_imp {
- _DecayFunc __fd;
+template<class _Op, class _Tuple,
+ class _Idxs = typename __make_tuple_indices<tuple_size<_Tuple>::value>::type>
+struct __perfect_forward_impl;
-public:
- __not_fn_imp() = delete;
+template<class _Op, class... _Bound, size_t... _Idxs>
+struct __perfect_forward_impl<_Op, __tuple_types<_Bound...>, __tuple_indices<_Idxs...>>
+{
+ tuple<_Bound...> __bound_;
- template <class ..._Args>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
- auto operator()(_Args&& ...__args) &
- noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)))
- -> decltype( !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))
- { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); }
+ template<class... _Args>
+ _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) &
+ noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...)))
+ -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...))
+ {return _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...);}
- template <class ..._Args>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
- auto operator()(_Args&& ...__args) &&
- noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)))
- -> decltype( !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))
- { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); }
+ template<class... _Args>
+ _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const&
+ noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...)))
+ -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...))
+ {return _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...);}
- template <class ..._Args>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
- auto operator()(_Args&& ...__args) const&
- noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)))
- -> decltype( !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))
- { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); }
+ template<class... _Args>
+ _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) &&
+ noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
+ _VSTD::forward<_Args>(__args)...)))
+ -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
+ _VSTD::forward<_Args>(__args)...))
+ {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
+ _VSTD::forward<_Args>(__args)...);}
+ template<class... _Args>
+ _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const&&
+ noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
+ _VSTD::forward<_Args>(__args)...)))
+ -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
+ _VSTD::forward<_Args>(__args)...))
+ {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
+ _VSTD::forward<_Args>(__args)...);}
- template <class ..._Args>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
- auto operator()(_Args&& ...__args) const&&
- noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)))
- -> decltype( !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))
- { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); }
+ template<class _Fn = typename tuple_element<0, tuple<_Bound...>>::type,
+ class = _EnableIf<is_copy_constructible_v<_Fn>>>
+ constexpr __perfect_forward_impl(__perfect_forward_impl const& __other)
+ : __bound_(__other.__bound_) {}
-private:
- template <class _RawFunc,
- class = enable_if_t<!is_same<decay_t<_RawFunc>, __not_fn_imp>::value>>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
- explicit __not_fn_imp(_RawFunc&& __rf)
- : __fd(_VSTD::forward<_RawFunc>(__rf)) {}
+ template<class _Fn = typename tuple_element<0, tuple<_Bound...>>::type,
+ class = _EnableIf<is_move_constructible_v<_Fn>>>
+ constexpr __perfect_forward_impl(__perfect_forward_impl && __other)
+ : __bound_(_VSTD::move(__other.__bound_)) {}
- template <class _RawFunc>
- friend inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
- __not_fn_imp<decay_t<_RawFunc>> not_fn(_RawFunc&&);
+ template<class... _BoundArgs>
+ explicit constexpr __perfect_forward_impl(_BoundArgs&&... __bound) :
+ __bound_(_VSTD::forward<_BoundArgs>(__bound)...) { }
};
-template <class _RawFunc>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
-__not_fn_imp<decay_t<_RawFunc>> not_fn(_RawFunc&& __fn) {
- return __not_fn_imp<decay_t<_RawFunc>>(_VSTD::forward<_RawFunc>(__fn));
+template<class _Op, class... _Args>
+using __perfect_forward =
+ __perfect_forward_impl<_Op, __tuple_types<decay_t<_Args>...>>;
+
+struct __not_fn_op
+{
+ template<class... _Args>
+ static _LIBCPP_CONSTEXPR_AFTER_CXX17 auto __call(_Args&&... __args)
+ noexcept(noexcept(!_VSTD::invoke(_VSTD::forward<_Args>(__args)...)))
+ -> decltype( !_VSTD::invoke(_VSTD::forward<_Args>(__args)...))
+ { return !_VSTD::invoke(_VSTD::forward<_Args>(__args)...); }
+};
+
+template<class _Fn,
+ class = _EnableIf<is_constructible_v<decay_t<_Fn>, _Fn> &&
+ is_move_constructible_v<_Fn>>>
+_LIBCPP_CONSTEXPR_AFTER_CXX17 auto not_fn(_Fn&& __f)
+{
+ return __perfect_forward<__not_fn_op, _Fn>(_VSTD::forward<_Fn>(__f));
}
-#endif
+#endif // _LIBCPP_STD_VER > 14
+
+#if _LIBCPP_STD_VER > 17
+
+struct __bind_front_op
+{
+ template<class... _Args>
+ constexpr static auto __call(_Args&&... __args)
+ noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Args>(__args)...)))
+ -> decltype( _VSTD::invoke(_VSTD::forward<_Args>(__args)...))
+ { return _VSTD::invoke(_VSTD::forward<_Args>(__args)...); }
+};
+
+template<class _Fn, class... _Args,
+ class = _EnableIf<conjunction<is_constructible<decay_t<_Fn>, _Fn>,
+ is_move_constructible<decay_t<_Fn>>,
+ is_constructible<decay_t<_Args>, _Args>...,
+ is_move_constructible<decay_t<_Args>>...
+ >::value>>
+constexpr auto bind_front(_Fn&& __f, _Args&&... __args)
+{
+ return __perfect_forward<__bind_front_op, _Fn, _Args...>(_VSTD::forward<_Fn>(__f),
+ _VSTD::forward<_Args>(__args)...);
+}
+
+#endif // _LIBCPP_STD_VER > 17
// struct hash<T*> in <memory>