kokkos-execution 0.0.1
Loading...
Searching...
No Matches
elide.hpp
Go to the documentation of this file.
1// NOLINTBEGIN
2/*
3 * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 * Copyright (c) 2025 Robert Leahy. All rights reserved.
5 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 *
7 * Licensed under the Apache License, Version 2.0 with LLVM Exceptions (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * https://llvm.org/LICENSE.txt
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#pragma once
21
22#include <concepts>
23#include <functional>
24#include <tuple>
25#include <type_traits>
26#include <utility>
27
29
30namespace detail::elide {
31
32template <typename T>
33concept result = !std::same_as<void, T>;
34
35template <typename T, typename... Args>
36concept c = std::invocable<T, Args...> && result<std::invoke_result_t<T, Args...>> && std::is_reference_v<T>
37 && (std::is_reference_v<Args> && ...);
38
39template <typename T, typename... Args>
40concept lvalue = std::invocable<T&, Args&...> && result<std::invoke_result_t<T&, Args&...>>;
41
42struct tombstone { };
43
44template <typename T, typename... Args>
45struct lvalue_result : std::type_identity<tombstone> { };
46
47template <typename T, typename... Args>
48requires lvalue<T, Args...>
49struct lvalue_result<T, Args...> : std::invoke_result<T&, Args&...> { };
50
51} // namespace detail::elide
52
53template <typename T, typename... Args>
54requires detail::elide::c<T, Args...>
55struct elide {
56 elide() = delete;
57 elide(const elide&) = delete;
58 elide& operator=(const elide&) = delete;
59
60 constexpr explicit elide(T t, Args... args) noexcept
61 : t_(std::forward<T>(t))
62 , args_(std::forward<Args>(args)...) {
63 }
64 private:
65 static constexpr bool rvalue_noexcept_ = std::is_nothrow_invocable_v<T, Args...>;
66 static constexpr bool lvalue_noexcept_ = std::is_nothrow_invocable_v<T&, Args&...>;
67 using rvalue_result_type_ = std::invoke_result_t<T, Args...>;
68 using lvalue_result_type_ = typename detail::elide::lvalue_result<T, Args...>::type;
69 public:
70 constexpr operator rvalue_result_type_() const && noexcept(rvalue_noexcept_) {
71 return std::apply(
72 [&](auto&&... args) noexcept(rvalue_noexcept_) {
73 return std::invoke(std::forward<T>(t_), std::forward<Args>(args)...);
74 },
75 args_);
76 }
77
78 constexpr rvalue_result_type_ operator()() const && noexcept(rvalue_noexcept_) {
79 return rvalue_result_type_(std::move(*this));
80 }
81
82 constexpr operator lvalue_result_type_() const & noexcept(lvalue_noexcept_) {
83 if constexpr (detail::elide::lvalue<T, Args...>) {
84 return std::apply(
85 [&](auto&&... args) noexcept(lvalue_noexcept_) { return std::invoke(t_, args...); }, args_);
86 } else {
87 return {};
88 }
89 }
90
91 constexpr lvalue_result_type_
92 operator()() const & noexcept(lvalue_noexcept_) requires detail::elide::lvalue<T, Args...>
93 {
94 return rvalue_result_type_(*this);
95 }
96 private:
97 [[no_unique_address]]
98 T t_;
99 [[no_unique_address]]
100 std::tuple<Args...> args_;
101};
102
103template <typename T, typename... Args>
104explicit elide(T&&, Args&&...) -> elide<T&&, Args&&...>;
105
106} // namespace experimental::execution
107
108// NOLINTEND
typename detail::elide::lvalue_result< T, Args... >::type lvalue_result_type_
Definition elide.hpp:68
constexpr lvalue_result_type_ operator()() const &noexcept(lvalue_noexcept_)
Definition elide.hpp:92
static constexpr bool rvalue_noexcept_
Definition elide.hpp:65
constexpr elide(T t, Args... args) noexcept
Definition elide.hpp:60
elide(const elide &)=delete
static constexpr bool lvalue_noexcept_
Definition elide.hpp:66
std::invoke_result_t< T, Args... > rvalue_result_type_
Definition elide.hpp:67
constexpr rvalue_result_type_ operator()() const &&noexcept(rvalue_noexcept_)
Definition elide.hpp:78
std::tuple< Args... > args_
Definition elide.hpp:100
elide & operator=(const elide &)=delete