1- // SPDX-FileCopyrightText: 2026 CExA- project
1+ // SPDX-FileCopyrightText: Copyright (C) The CExA project
22// SPDX-License-Identifier: MIT or Apache-2.0 with LLVM-exception
33#pragma once
44
99#include " traits.hpp"
1010#include " tuple.hpp"
1111
12+ #if defined(CEXA_HAS_CXX23)
13+ #include < functional>
14+ #endif
15+
1216namespace cexa {
1317
1418namespace impl {
@@ -21,7 +25,7 @@ template <class C, class Pointed, class Object, class... Args>
2125KOKKOS_INLINE_FUNCTION constexpr decltype (auto ) invoke_ptr(Pointed C::* member,
2226 Object&& object,
2327 Args&&... args) {
24- using object_t = remove_cvref_t <Object>;
28+ using object_t = std:: remove_cvref_t <Object>;
2529 constexpr bool is_wrapped = is_reference_wrapper_v<object_t >;
2630 constexpr bool is_derived_object =
2731 std::is_same_v<C, object_t > || std::is_base_of_v<C, object_t >;
@@ -48,9 +52,11 @@ KOKKOS_INLINE_FUNCTION constexpr decltype(auto) invoke_ptr(Pointed C::* member,
4852 }
4953}
5054
55+ // f may be a host function
56+ CEXA_NVCC_HOST_DEVICE_CHECK_DISABLE
5157template <class F , class ... Args>
5258KOKKOS_INLINE_FUNCTION constexpr decltype (auto ) invoke(F&& f, Args&&... args) {
53- if constexpr (std::is_member_pointer_v<remove_cvref_t <F>>) {
59+ if constexpr (std::is_member_pointer_v<std:: remove_cvref_t <F>>) {
5460 return invoke_ptr (f, std::forward<Args>(args)...);
5561 } else {
5662 return (std::forward<F>(f))(std::forward<Args>(args)...);
@@ -63,13 +69,15 @@ KOKKOS_INLINE_FUNCTION constexpr decltype(auto) apply(
6369 return invoke (std::forward<F>(f), cexa::get<I>(std::forward<Tuple>(t))...);
6470}
6571
72+ // This might call a host only constructor
73+ CEXA_NVCC_HOST_DEVICE_CHECK_DISABLE
6674template <class T , class Tuple , std::size_t ... I>
6775KOKKOS_INLINE_FUNCTION constexpr T make_from_tuple (Tuple&& t,
6876 std::index_sequence<I...>) {
6977 return T (cexa::get<I>(std::forward<Tuple>(t))...);
7078}
7179
72- template <class U , class T , std::size_t = tuple_size_v<impl ::remove_cvref_t <T>>>
80+ template <class U , class T , std::size_t = tuple_size_v<std ::remove_cvref_t <T>>>
7381struct make_tuple_constraint : std::true_type {};
7482
7583template <class U , class Tuple >
@@ -78,7 +86,7 @@ struct make_tuple_constraint<U, Tuple, 1> {
7886 U, decltype (get<0 >(std::declval<Tuple>()))>;
7987};
8088
81- template <class T , class Tuple , class seq >
89+ template <class T , class Tuple , class Seq >
8290struct is_constructible_from_tuple ;
8391
8492template <class T , class Tuple , std::size_t ... Ints>
@@ -91,28 +99,47 @@ template <class T, class Tuple>
9199inline constexpr bool is_constructible_from_tuple_v =
92100 is_constructible_from_tuple<T, Tuple,
93101 std::make_index_sequence<tuple_size_v<
94- impl::remove_cvref_t <Tuple>>>>::value;
102+ std::remove_cvref_t <Tuple>>>>::value;
103+
104+ #if defined(CEXA_HAS_CXX23)
105+ template <class F , class Tuple , class Other >
106+ struct is_nothrow_applicable : std::false_type {};
107+
108+ template <class F , class Tuple , std::size_t ... Is>
109+ struct is_nothrow_applicable <F, Tuple, std::index_sequence<Is...>> {
110+ static constexpr bool value = noexcept (
111+ std::invoke (std::declval<F>(), get<Is>(std::declval<Tuple>())...));
112+ };
95113
114+ template <class F , class Tuple >
115+ constexpr bool is_nothrow_applicable_v =
116+ is_nothrow_applicable<F, Tuple,
117+ decltype (std::make_index_sequence<tuple_size_v<
118+ std::remove_cvref_t <Tuple>>>{})>::value;
119+ #endif
96120} // namespace impl
97121
98122template <class F , class Tuple >
99- KOKKOS_INLINE_FUNCTION constexpr decltype (auto ) apply(F&& f, Tuple&& t) {
100- static_assert (impl::is_tuple_v<impl::remove_cvref_t <Tuple>>,
123+ KOKKOS_INLINE_FUNCTION constexpr decltype (auto ) apply(F&& f, Tuple&& t)
124+ #if defined(CEXA_HAS_CXX23)
125+ noexcept (impl::is_nothrow_applicable_v<F, Tuple>)
126+ #endif
127+ {
128+ static_assert (impl::is_tuple_v<std::remove_cvref_t <Tuple>>,
101129 " cexa::apply can only be called with cexa::tuple" );
102130 return impl::apply (
103131 std::forward<F>(f), std::forward<Tuple>(t),
104132 std::make_index_sequence<tuple_size_v<std::remove_reference_t <Tuple>>>{});
105133}
106134
107- template <
108- class T , class Tuple ,
109- class = std::enable_if_t <impl::is_constructible_from_tuple_v<T, Tuple>>>
135+ template <class T , class Tuple >
136+ requires impl::is_constructible_from_tuple_v<T, Tuple>
110137KOKKOS_INLINE_FUNCTION constexpr T make_from_tuple (Tuple&& t) {
111- static_assert (impl::is_tuple_v<impl ::remove_cvref_t <Tuple>>,
138+ static_assert (impl::is_tuple_v<std ::remove_cvref_t <Tuple>>,
112139 " cexa::make_from_tuple can only be called with cexa::tuple" );
113140 constexpr std::size_t size = tuple_size_v<std::remove_reference_t <Tuple>>;
114141 static_assert (
115- impl::make_tuple_constraint<T, impl ::remove_cvref_t <Tuple>>::value);
142+ impl::make_tuple_constraint<T, std ::remove_cvref_t <Tuple>>::value);
116143 return impl::make_from_tuple<T>(std::forward<Tuple>(t),
117144 std::make_index_sequence<size>{});
118145}
0 commit comments