xref: /llvm-project/libcxx/include/__functional/compose.h (revision 9783f28cbb155e4a8d49c12e1c60ce14dcfaf0c7)
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_COMPOSE_H
1189a7bdb1SLouis Dionne #define _LIBCPP___FUNCTIONAL_COMPOSE_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 
1989a7bdb1SLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2089a7bdb1SLouis Dionne #  pragma GCC system_header
2189a7bdb1SLouis Dionne #endif
2289a7bdb1SLouis Dionne 
2389a7bdb1SLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD
2489a7bdb1SLouis Dionne 
254f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20
2689a7bdb1SLouis Dionne 
2789a7bdb1SLouis Dionne struct __compose_op {
2889a7bdb1SLouis Dionne   template <class _Fn1, class _Fn2, class... _Args>
29*9783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn1&& __f1, _Fn2&& __f2, _Args&&... __args) const noexcept(noexcept(
30*9783f28cSLouis Dionne       std::invoke(std::forward<_Fn1>(__f1), std::invoke(std::forward<_Fn2>(__f2), std::forward<_Args>(__args)...))))
31*9783f28cSLouis Dionne       -> decltype(std::invoke(std::forward<_Fn1>(__f1),
32*9783f28cSLouis Dionne                               std::invoke(std::forward<_Fn2>(__f2), std::forward<_Args>(__args)...))) {
33*9783f28cSLouis Dionne     return std::invoke(std::forward<_Fn1>(__f1), std::invoke(std::forward<_Fn2>(__f2), std::forward<_Args>(__args)...));
34*9783f28cSLouis Dionne   }
3589a7bdb1SLouis Dionne };
3689a7bdb1SLouis Dionne 
3789a7bdb1SLouis Dionne template <class _Fn1, class _Fn2>
3889a7bdb1SLouis Dionne struct __compose_t : __perfect_forward<__compose_op, _Fn1, _Fn2> {
3989a7bdb1SLouis Dionne   using __perfect_forward<__compose_op, _Fn1, _Fn2>::__perfect_forward;
4089a7bdb1SLouis Dionne };
4189a7bdb1SLouis Dionne 
4289a7bdb1SLouis Dionne template <class _Fn1, class _Fn2>
43*9783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr auto __compose(_Fn1&& __f1, _Fn2&& __f2) noexcept(
44*9783f28cSLouis Dionne     noexcept(__compose_t<decay_t<_Fn1>, decay_t<_Fn2>>(std::forward<_Fn1>(__f1), std::forward<_Fn2>(__f2))))
45*9783f28cSLouis Dionne     -> decltype(__compose_t<decay_t<_Fn1>, decay_t<_Fn2>>(std::forward<_Fn1>(__f1), std::forward<_Fn2>(__f2))) {
46*9783f28cSLouis Dionne   return __compose_t<decay_t<_Fn1>, decay_t<_Fn2>>(std::forward<_Fn1>(__f1), std::forward<_Fn2>(__f2));
47*9783f28cSLouis Dionne }
4889a7bdb1SLouis Dionne 
494f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20
5089a7bdb1SLouis Dionne 
5189a7bdb1SLouis Dionne _LIBCPP_END_NAMESPACE_STD
5289a7bdb1SLouis Dionne 
5389a7bdb1SLouis Dionne #endif // _LIBCPP___FUNCTIONAL_COMPOSE_H
54