Skip to content

Commit a58a1d6

Browse files
authored
Update tuple to C++20 (#9)
* Update to use c++20 * Fix constraints and clang-tidy warnings in the implementation * Ignore/fix some of the tests with gcc or nvcc * Fix the copyright notice in the extra tests * Fix some unused variable warnings * Fix nvcc host function called from host device function warnings * Update the clang tidy and fix the new warnings * misc changes - fix more clang-tidy warnings - revert the use of requires for cexa::get - don't use std::reference_constructs_from_temporary, as support varies, especially for older compilers * Use if defined instead of ifdef * Remove an extra semicolon and some unused parameters * Fix warnings and use sfinae for the tuple-like ctor * Fix compilation with nvcc 12.2 * Remove the date from the copyright statement * Remove a useless comment
1 parent ab346c3 commit a58a1d6

102 files changed

Lines changed: 839 additions & 1420 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

tuple/.clang-tidy

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@ Checks: >
2626
-cppcoreguidelines-narrowing-conversions,
2727
-cppcoreguidelines-non-private-member-variables-in-classes,
2828
-cppcoreguidelines-owning-memory,
29+
-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,
2930
-cppcoreguidelines-pro-bounds-constant-array-index,
3031
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
3132
-cppcoreguidelines-pro-type-member-init,
3233
-cppcoreguidelines-pro-type-reinterpret-cast,
3334
google-*,
3435
-google-readability-todo,
36+
-google-runtime-float,
3537
-google-runtime-int,
3638
hicpp-*,
3739
-hicpp-explicit-conversions,
@@ -48,7 +50,7 @@ Checks: >
4850
modernize-*,
4951
-modernize-pass-by-value,
5052
-modernize-use-auto,
51-
-modernize-use-constraints,
53+
-modernize-use-integer-sign-comparison,
5254
-modernize-use-nodiscard,
5355
-modernize-use-trailing-return-type,
5456
performance-*,
@@ -58,23 +60,20 @@ Checks: >
5860
-portability-avoid-pragma-once,
5961
-portability-template-virtual-member-function,
6062
readability-*,
61-
-readability-else-after-return,
6263
-readability-function-cognitive-complexity,
63-
-readability-identifier-naming,
6464
-readability-identifier-length,
6565
-readability-implicit-bool-conversion,
6666
-readability-magic-numbers,
6767
-readability-math-missing-parentheses,
6868
-readability-named-parameter,
6969
-readability-redundant-access-specifiers,
70-
-readability-use-concise-preprocessor-directives,
71-
-cert-oop54-cpp
70+
-readability-use-concise-preprocessor-directives
7271
WarningsAsErrors: '*'
7372
CheckOptions:
7473
- key: cppcoreguidelines-rvalue-reference-param-not-moved.AllowPartialMove
7574
value: 'true'
7675
- key: readability-identifier-naming.ClassCase
77-
value: CamelCase
76+
value: lower_case
7877
- key: readability-identifier-naming.FunctionCase
7978
value: lower_case
8079
- key: readability-identifier-naming.FunctionIgnoredRegexp
@@ -88,8 +87,6 @@ CheckOptions:
8887
- key: readability-identifier-naming.PrivateMemberPrefix
8988
value: m_
9089
- key: readability-identifier-naming.StructCase
91-
value: CamelCase
92-
- key: readability-identifier-naming.StructIgnoredRegexp
93-
value: '(is_.*|sum|prod|land|lor|band|bor|bxor|min|max|minmax|coordinate_of|chunk_traits|rebind|kwArgs_fft)'
90+
value: lower_case
9491
- key: readability-identifier-naming.TemplateParameterCase
9592
value: CamelCase

tuple/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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
cmake_minimum_required(VERSION 3.22)
44

@@ -28,6 +28,7 @@ add_library(cexa.tuple INTERFACE)
2828
# )
2929
target_include_directories(cexa.tuple INTERFACE "${CMAKE_CURRENT_LIST_DIR}/include")
3030
target_link_libraries(cexa.tuple INTERFACE Kokkos::kokkos)
31+
target_compile_features(cexa.tuple INTERFACE cxx_std_20)
3132
add_library(cexa::tuple ALIAS cexa.tuple)
3233

3334
if(CEXA_TUPLE_ENABLE_TESTS)

tuple/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
SPDX-FileCopyrightText: 2026 CExA-project
2+
SPDX-FileCopyrightText: Copyright (C) The CExA project
33
44
SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
55
-->

tuple/include/impl/apply.hpp

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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

@@ -9,6 +9,10 @@
99
#include "traits.hpp"
1010
#include "tuple.hpp"
1111

12+
#if defined(CEXA_HAS_CXX23)
13+
#include <functional>
14+
#endif
15+
1216
namespace cexa {
1317

1418
namespace impl {
@@ -21,7 +25,7 @@ template <class C, class Pointed, class Object, class... Args>
2125
KOKKOS_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
5157
template <class F, class... Args>
5258
KOKKOS_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
6674
template <class T, class Tuple, std::size_t... I>
6775
KOKKOS_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>>>
7381
struct make_tuple_constraint : std::true_type {};
7482

7583
template <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>
8290
struct is_constructible_from_tuple;
8391

8492
template <class T, class Tuple, std::size_t... Ints>
@@ -91,28 +99,47 @@ template <class T, class Tuple>
9199
inline 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

98122
template <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>
110137
KOKKOS_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
}

tuple/include/impl/creation.hpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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

@@ -13,7 +13,7 @@ namespace cexa {
1313

1414
// tuple.creation
1515
template <class... TTypes>
16-
KOKKOS_INLINE_FUNCTION constexpr tuple<impl::unwrap_ref_decay_t<TTypes>...>
16+
KOKKOS_INLINE_FUNCTION constexpr tuple<std::unwrap_ref_decay_t<TTypes>...>
1717
make_tuple(TTypes&&... t) {
1818
return {std::forward<TTypes>(t)...};
1919
}
@@ -66,18 +66,20 @@ struct cartesian_product
6666
std::remove_reference_t<Tuples>>::value>...> {
6767
};
6868

69+
// We might call std::get depending on the types in Tuples
70+
CEXA_NVCC_HOST_DEVICE_CHECK_DISABLE
6971
template <class... Tuples, std::size_t... Ints1, std::size_t... Ints2>
7072
KOKKOS_FORCEINLINE_FUNCTION constexpr tuple<cexa::tuple_element_t<
7173
Ints1,
72-
impl::remove_cvref_t<cexa::tuple_element_t<Ints2, tuple<Tuples...>>>>...>
74+
std::remove_cvref_t<cexa::tuple_element_t<Ints2, tuple<Tuples...>>>>...>
7375
tuple_cat_impl(tuple<Tuples...>&& tuples, std::index_sequence<Ints1...>,
7476
std::index_sequence<Ints2...>) {
7577
return {get<Ints1>(std::move(get<Ints2>(tuples)))...};
7678
}
7779
} // namespace impl
7880

79-
template <class... Tuples,
80-
class = std::enable_if_t<(impl::is_tuple_like<Tuples>::value && ...)>>
81+
template <class... Tuples>
82+
requires(impl::is_tuple_like<Tuples>::value && ...)
8183
KOKKOS_INLINE_FUNCTION constexpr auto tuple_cat(Tuples&&... tuples) {
8284
using cartesian_product_t = impl::cartesian_product<Tuples...>;
8385
return impl::tuple_cat_impl(cexa::forward_as_tuple(tuples...),

tuple/include/impl/helper.hpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
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

55
#include <array>
66
#include <cstddef>
7-
#include <type_traits> // integral_constant
8-
#if defined(CEXA_HAS_CXX20)
7+
#include <type_traits>
98
#include <ranges>
10-
#endif
119

1210
#include "tuple_fwd.hpp"
1311
#include "traits.hpp"
@@ -65,7 +63,6 @@ struct tuple_element<I, std::array<T, N>> {
6563
using type = T;
6664
};
6765

68-
#if defined(CEXA_HAS_CXX20)
6966
template <class I, class S, std::ranges::subrange_kind K>
7067
struct tuple_element<0, std::ranges::subrange<I, S, K>> {
7168
using type = I;
@@ -75,10 +72,9 @@ template <class I, class S, std::ranges::subrange_kind K>
7572
struct tuple_element<1, std::ranges::subrange<I, S, K>> {
7673
using type = S;
7774
};
78-
#endif
7975

8076
template <std::size_t I, class T>
81-
using tuple_element_t = typename tuple_element<I, T>::type;
77+
using tuple_element_t = tuple_element<I, T>::type;
8278

8379
// tuple_size
8480
template <class T>
@@ -108,24 +104,22 @@ struct tuple_size<std::pair<T, U>> : std::integral_constant<std::size_t, 2> {};
108104
template <class T, std::size_t N>
109105
struct tuple_size<std::array<T, N>> : std::integral_constant<std::size_t, N> {};
110106

111-
#if defined(CEXA_HAS_CXX20)
112107
template <class I, class S, std::ranges::subrange_kind K>
113108
struct tuple_size<std::ranges::subrange<I, S, K>>
114109
: std::integral_constant<std::size_t, 2> {};
115-
#endif
116110

117111
template <class T>
118112
inline constexpr std::size_t tuple_size_v = tuple_size<T>::value;
119113
} // namespace cexa
120114

121115
// NOTE: specializations of std::tuple_size and std::tuple_element for user
122116
// defined types are allowed.
123-
// NOLINTBEGIN(cert-dcl58-cpp)
117+
// NOLINTBEGIN(cert-dcl58-cpp,bugprone-std-namespace-modification)
124118
template <typename... Types>
125119
struct std::tuple_size<cexa::tuple<Types...>>
126120
: std::integral_constant<std::size_t, sizeof...(Types)> {};
127121

128122
template <std::size_t I, typename... Types>
129123
struct std::tuple_element<I, cexa::tuple<Types...>>
130124
: cexa::tuple_element<I, cexa::tuple<Types...>> {};
131-
// NOLINTEND(cert-dcl58-cpp)
125+
// NOLINTEND(cert-dcl58-cpp,bugprone-std-namespace-modification)

tuple/include/impl/ignore.hpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,13 @@
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

5-
#include "macros.hpp"
65
#include <Kokkos_Macros.hpp>
76

87
namespace cexa {
98
namespace impl {
10-
// FIXME: address this
11-
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
129
struct ignore_t {
13-
KOKKOS_DEFAULTED_FUNCTION constexpr ignore_t() = default;
14-
KOKKOS_DEFAULTED_FUNCTION
15-
#if defined(CEXA_HAS_CXX20)
16-
constexpr
17-
#endif
18-
~ignore_t() = default;
19-
20-
template <typename T>
10+
template <class T>
2111
KOKKOS_INLINE_FUNCTION constexpr const ignore_t& operator=(
2212
const T&) const noexcept {
2313
return *this;

tuple/include/impl/macros.hpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
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

5+
#include <Kokkos_Macros.hpp>
6+
57
#if defined(_MSVC_LANG)
68
#define CEXA_STD_VERSION _MSVC_LANG
79
#else
810
#define CEXA_STD_VERSION __cplusplus
911
#endif
1012

11-
#if CEXA_STD_VERSION >= 202002L
12-
#define CEXA_HAS_CXX20
13-
#endif
14-
#if CEXA_STD_VERSION >= 202302L
13+
// GCC 13 defines __cplusplus to 202100L when in c++23
14+
#if (defined(KOKKOS_COMPILER_GNU) && CEXA_STD_VERSION >= 202100L) || \
15+
CEXA_STD_VERSION >= 202302L
1516
#define CEXA_HAS_CXX23
1617
#endif
18+
19+
#if defined(KOKKOS_COMPILER_NVCC)
20+
#define CEXA_NVCC_HOST_DEVICE_CHECK_DISABLE _Pragma("nv_exec_check_disable")
21+
#else
22+
#define CEXA_NVCC_HOST_DEVICE_CHECK_DISABLE
23+
#endif
24+
25+
// FIXME: As of cuda 13, support for operator<=> in device code is still brittle
26+
#if !defined(KOKKOS_COMPILER_NVCC)
27+
#define CEXA_TUPLE_IMPL_USE_SPACESHIP_OPERATOR
28+
#endif

0 commit comments

Comments
 (0)