[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / libcxx / test / support / invocable_with_telemetry.h
blob612bbec639d4664584f4996663dfb9420223eeec
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef TEST_SUPPORT_INVOCABLE_WITH_TELEMETRY_H
10 #define TEST_SUPPORT_INVOCABLE_WITH_TELEMETRY_H
12 #include <cassert>
13 #include <concepts>
14 #include <functional>
15 #include <utility>
17 #if TEST_STD_VER < 20
18 # error invocable_with_telemetry requires C++20
19 #else
20 struct invocable_telemetry {
21 int invocations;
22 int moves;
23 int copies;
26 template <class F>
27 class invocable_with_telemetry {
28 public:
29 constexpr invocable_with_telemetry(F f, invocable_telemetry& telemetry) : f_(f), telemetry_(&telemetry) {}
31 constexpr invocable_with_telemetry(invocable_with_telemetry&& other)
32 requires std::move_constructible<F>
33 : f_(std::move(other.f_)),
34 telemetry_(assert(other.telemetry_ != nullptr), std::exchange(other.telemetry_, nullptr)) {
35 ++telemetry_->moves;
38 constexpr invocable_with_telemetry(invocable_with_telemetry const& other)
39 requires std::copy_constructible<F>
40 : f_(other.f_), telemetry_((assert(other.telemetry_ != nullptr), other.telemetry_)) {
41 ++telemetry_->copies;
44 constexpr invocable_with_telemetry& operator=(invocable_with_telemetry&& other)
45 requires std::movable<F>
47 // Not using move-and-swap idiom to ensure that copies and moves remain accurate.
48 assert(&other != this);
49 assert(other.telemetry_ != nullptr);
51 f_ = std::move(other.f_);
52 telemetry_ = std::exchange(other.telemetry_, nullptr);
54 ++telemetry_->moves;
55 return *this;
58 constexpr invocable_with_telemetry& operator=(invocable_with_telemetry const& other)
59 requires std::copyable<F>
61 // Not using copy-and-swap idiom to ensure that copies and moves remain accurate.
62 assert(&other != this);
63 assert(other.telemetry_ != nullptr);
65 f_ = other.f_;
66 telemetry_ = other.telemetry_;
68 ++telemetry_->copies;
69 return *this;
72 template <class... Args>
73 requires std::invocable<F&, Args...>
74 constexpr decltype(auto) operator()(Args&&... args) noexcept(std::is_nothrow_invocable_v<F&, Args...>) {
75 assert(telemetry_);
76 ++telemetry_->invocations;
77 return std::invoke(f_, std::forward<Args>(args)...);
80 private:
81 F f_ = F();
82 invocable_telemetry* telemetry_ = nullptr;
85 template <class F>
86 invocable_with_telemetry(F f, int& invocations, int& moves, int& copies) -> invocable_with_telemetry<F>;
88 #endif // TEST_STD_VER < 20
89 #endif // TEST_SUPPORT_INVOCABLE_WITH_TELEMETRY_H