189a7bdb1SLouis Dionne // -*- C++ -*- 289a7bdb1SLouis Dionne //===----------------------------------------------------------------------===// 389a7bdb1SLouis Dionne // 489a7bdb1SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 589a7bdb1SLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 689a7bdb1SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 789a7bdb1SLouis Dionne // 889a7bdb1SLouis Dionne //===----------------------------------------------------------------------===// 989a7bdb1SLouis Dionne 1089a7bdb1SLouis Dionne #ifndef _LIBCPP___FUNCTIONAL_BIND_BACK_H 1189a7bdb1SLouis Dionne #define _LIBCPP___FUNCTIONAL_BIND_BACK_H 1289a7bdb1SLouis Dionne 1389a7bdb1SLouis Dionne #include <__config> 1489a7bdb1SLouis Dionne #include <__functional/invoke.h> 1589a7bdb1SLouis Dionne #include <__functional/perfect_forward.h> 1679702f7fSIan Anderson #include <__type_traits/decay.h> 1789a7bdb1SLouis Dionne #include <__utility/forward.h> 1889a7bdb1SLouis Dionne #include <__utility/integer_sequence.h> 1989a7bdb1SLouis Dionne #include <tuple> 2089a7bdb1SLouis Dionne 2189a7bdb1SLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2289a7bdb1SLouis Dionne # pragma GCC system_header 2389a7bdb1SLouis Dionne #endif 2489a7bdb1SLouis Dionne 2589a7bdb1SLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD 2689a7bdb1SLouis Dionne 274f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20 2889a7bdb1SLouis Dionne 2989a7bdb1SLouis Dionne template <size_t _NBound, class = make_index_sequence<_NBound>> 3089a7bdb1SLouis Dionne struct __bind_back_op; 3189a7bdb1SLouis Dionne 3289a7bdb1SLouis Dionne template <size_t _NBound, size_t... _Ip> 3389a7bdb1SLouis Dionne struct __bind_back_op<_NBound, index_sequence<_Ip...>> { 345a4f177cSPeter Kasting template <class _Fn, class _BoundArgs, class... _Args> 355a4f177cSPeter Kasting _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn&& __f, _BoundArgs&& __bound_args, _Args&&... __args) const 369783f28cSLouis Dionne noexcept(noexcept(std::invoke(std::forward<_Fn>(__f), 379783f28cSLouis Dionne std::forward<_Args>(__args)..., 389783f28cSLouis Dionne std::get<_Ip>(std::forward<_BoundArgs>(__bound_args))...))) 399783f28cSLouis Dionne -> decltype(std::invoke(std::forward<_Fn>(__f), 409783f28cSLouis Dionne std::forward<_Args>(__args)..., 419783f28cSLouis Dionne std::get<_Ip>(std::forward<_BoundArgs>(__bound_args))...)) { 429783f28cSLouis Dionne return std::invoke(std::forward<_Fn>(__f), 439783f28cSLouis Dionne std::forward<_Args>(__args)..., 449783f28cSLouis Dionne std::get<_Ip>(std::forward<_BoundArgs>(__bound_args))...); 459783f28cSLouis Dionne } 4689a7bdb1SLouis Dionne }; 4789a7bdb1SLouis Dionne 4889a7bdb1SLouis Dionne template <class _Fn, class _BoundArgs> 4989a7bdb1SLouis Dionne struct __bind_back_t : __perfect_forward<__bind_back_op<tuple_size_v<_BoundArgs>>, _Fn, _BoundArgs> { 5089a7bdb1SLouis Dionne using __perfect_forward<__bind_back_op<tuple_size_v<_BoundArgs>>, _Fn, _BoundArgs>::__perfect_forward; 5189a7bdb1SLouis Dionne }; 5289a7bdb1SLouis Dionne 5348c805baSChristopher Di Bella template <class _Fn, class... _Args> 5448c805baSChristopher Di Bella requires is_constructible_v<decay_t<_Fn>, _Fn> && is_move_constructible_v<decay_t<_Fn>> && 5548c805baSChristopher Di Bella (is_constructible_v<decay_t<_Args>, _Args> && ...) && (is_move_constructible_v<decay_t<_Args>> && ...) 569783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) noexcept( 579783f28cSLouis Dionne noexcept(__bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>( 589783f28cSLouis Dionne std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...)))) 599783f28cSLouis Dionne -> decltype(__bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>( 609783f28cSLouis Dionne std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...))) { 619783f28cSLouis Dionne return __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>( 629783f28cSLouis Dionne std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...)); 639783f28cSLouis Dionne } 6489a7bdb1SLouis Dionne 65*c8917048SJakub Mazurkiewicz # if _LIBCPP_STD_VER >= 23 66*c8917048SJakub Mazurkiewicz template <class _Fn, class... _Args> 67*c8917048SJakub Mazurkiewicz _LIBCPP_HIDE_FROM_ABI constexpr auto bind_back(_Fn&& __f, _Args&&... __args) { 68*c8917048SJakub Mazurkiewicz static_assert(is_constructible_v<decay_t<_Fn>, _Fn>, "bind_back requires decay_t<F> to be constructible from F"); 69*c8917048SJakub Mazurkiewicz static_assert(is_move_constructible_v<decay_t<_Fn>>, "bind_back requires decay_t<F> to be move constructible"); 70*c8917048SJakub Mazurkiewicz static_assert((is_constructible_v<decay_t<_Args>, _Args> && ...), 71*c8917048SJakub Mazurkiewicz "bind_back requires all decay_t<Args> to be constructible from respective Args"); 72*c8917048SJakub Mazurkiewicz static_assert((is_move_constructible_v<decay_t<_Args>> && ...), 73*c8917048SJakub Mazurkiewicz "bind_back requires all decay_t<Args> to be move constructible"); 74*c8917048SJakub Mazurkiewicz return __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>( 75*c8917048SJakub Mazurkiewicz std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...)); 76*c8917048SJakub Mazurkiewicz } 77*c8917048SJakub Mazurkiewicz # endif // _LIBCPP_STD_VER >= 23 78*c8917048SJakub Mazurkiewicz 794f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20 8089a7bdb1SLouis Dionne 8189a7bdb1SLouis Dionne _LIBCPP_END_NAMESPACE_STD 8289a7bdb1SLouis Dionne 8389a7bdb1SLouis Dionne #endif // _LIBCPP___FUNCTIONAL_BIND_BACK_H 84