LLVM 23.0.0git
STLForwardCompat.h
Go to the documentation of this file.
1//===- STLForwardCompat.h - Library features from future STLs ------C++ -*-===//
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//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file contains library features backported from future STL versions.
11///
12/// These should be replaced with their STL counterparts as the C++ version LLVM
13/// is compiled with is updated.
14///
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_ADT_STLFORWARDCOMPAT_H
18#define LLVM_ADT_STLFORWARDCOMPAT_H
19
20#include <optional>
21#include <tuple>
22#include <type_traits>
23#include <utility>
24
25namespace llvm {
26
27//===----------------------------------------------------------------------===//
28// Features from C++20
29//===----------------------------------------------------------------------===//
30
31namespace numbers {
32// clang-format off
33template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
34inline constexpr T e_v = T(0x1.5bf0a8b145769P+1); // (2.7182818284590452354) https://oeis.org/A001113
35template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
36inline constexpr T egamma_v = T(0x1.2788cfc6fb619P-1); // (.57721566490153286061) https://oeis.org/A001620
37template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
38inline constexpr T ln2_v = T(0x1.62e42fefa39efP-1); // (.69314718055994530942) https://oeis.org/A002162
39template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
40inline constexpr T ln10_v = T(0x1.26bb1bbb55516P+1); // (2.3025850929940456840) https://oeis.org/A002392
41template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
42inline constexpr T log2e_v = T(0x1.71547652b82feP+0); // (1.4426950408889634074)
43template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
44inline constexpr T log10e_v = T(0x1.bcb7b1526e50eP-2); // (.43429448190325182765)
45template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
46inline constexpr T pi_v = T(0x1.921fb54442d18P+1); // (3.1415926535897932385) https://oeis.org/A000796
47template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
48inline constexpr T inv_pi_v = T(0x1.45f306dc9c883P-2); // (.31830988618379067154) https://oeis.org/A049541
49template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
50inline constexpr T inv_sqrtpi_v = T(0x1.20dd750429b6dP-1); // (.56418958354775628695) https://oeis.org/A087197
51template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
52inline constexpr T sqrt2_v = T(0x1.6a09e667f3bcdP+0); // (1.4142135623730950488) https://oeis.org/A00219
53template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
54inline constexpr T inv_sqrt2_v = T(0x1.6a09e667f3bcdP-1); // (.70710678118654752440)
55template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
56inline constexpr T sqrt3_v = T(0x1.bb67ae8584caaP+0); // (1.7320508075688772935) https://oeis.org/A002194
57template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
58inline constexpr T inv_sqrt3_v = T(0x1.279a74590331cP-1); // (.57735026918962576451)
59template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
60inline constexpr T phi_v = T(0x1.9e3779b97f4a8P+0); // (1.6180339887498948482) https://oeis.org/A001622
61
62inline constexpr double e = e_v<double>;
63inline constexpr double egamma = egamma_v<double>;
64inline constexpr double ln2 = ln2_v<double>;
65inline constexpr double ln10 = ln10_v<double>;
66inline constexpr double log2e = log2e_v<double>;
67inline constexpr double log10e = log10e_v<double>;
68inline constexpr double pi = pi_v<double>;
69inline constexpr double inv_pi = inv_pi_v<double>;
70inline constexpr double inv_sqrtpi = inv_sqrtpi_v<double>;
71inline constexpr double sqrt2 = sqrt2_v<double>;
72inline constexpr double inv_sqrt2 = inv_sqrt2_v<double>;
73inline constexpr double sqrt3 = sqrt3_v<double>;
74inline constexpr double inv_sqrt3 = inv_sqrt3_v<double>;
75inline constexpr double phi = phi_v<double>;
76// clang-format on
77} // namespace numbers
78
79template <typename T>
80struct remove_cvref // NOLINT(readability-identifier-naming)
81{
82 using type = std::remove_cv_t<std::remove_reference_t<T>>;
83};
84
85template <typename T>
86using remove_cvref_t // NOLINT(readability-identifier-naming)
88
89// TODO: Remove this in favor of std::type_identity<T> once we switch to C++20.
90template <typename T>
91struct type_identity // NOLINT(readability-identifier-naming)
92{
93 using type = T;
94};
95
96// TODO: Remove this in favor of std::type_identity_t<T> once we switch to
97// C++20.
98template <typename T>
99using type_identity_t // NOLINT(readability-identifier-naming)
101
102namespace detail {
103template <class, template <class...> class Op, class... Args> struct detector {
104 using value_t = std::false_type;
105};
106template <template <class...> class Op, class... Args>
107struct detector<std::void_t<Op<Args...>>, Op, Args...> {
108 using value_t = std::true_type;
109};
110} // end namespace detail
111
112/// Detects if a given trait holds for some set of arguments 'Args'.
113/// For example, the given trait could be used to detect if a given type
114/// has a copy assignment operator:
115/// template<class T>
116/// using has_copy_assign_t = decltype(std::declval<T&>()
117/// = std::declval<const T&>());
118/// bool fooHasCopyAssign = is_detected<has_copy_assign_t, FooClass>::value;
119///
120/// NOTE: The C++20 standard has adopted concepts and requires clauses as a
121/// superior alternative to std::is_detected.
122///
123/// This utility is placed in STLForwardCompat.h as a reminder
124/// to migrate usages of llvm::is_detected to concepts and 'requires'
125/// clauses when the codebase adopts C++20.
126template <template <class...> class Op, class... Args>
127using is_detected = typename detail::detector<void, Op, Args...>::value_t;
128
129struct identity // NOLINT(readability-identifier-naming)
130{
131 using is_transparent = void;
132
133 template <typename T> constexpr T &&operator()(T &&self) const noexcept {
134 return std::forward<T>(self);
135 }
136};
137
138/// Returns a raw pointer that represents the same address as the argument.
139///
140/// This implementation can be removed once we move to C++20 where it's defined
141/// as std::to_address().
142///
143/// The std::pointer_traits<>::to_address(p) variations of these overloads has
144/// not been implemented.
145template <class Ptr> auto to_address(const Ptr &P) { return P.operator->(); }
146template <class T> constexpr T *to_address(T *P) {
147 static_assert(!std::is_function_v<T>);
148 return P;
149}
150
151/// C++20 constexpr invoke. This uses `std::apply` (constexpr in C++17) to
152/// achieve constexpr invocation.
153template <typename FnT, typename... ArgsT>
154constexpr std::invoke_result_t<FnT, ArgsT...>
155invoke(FnT &&Fn, ArgsT &&...Args) { // NOLINT(readability-identifier-naming)
156 return std::apply(std::forward<FnT>(Fn),
157 std::forward_as_tuple(std::forward<ArgsT>(Args)...));
158}
159
160//===----------------------------------------------------------------------===//
161// Features from C++23
162//===----------------------------------------------------------------------===//
163
164// TODO: Remove this in favor of std::optional<T>::transform once we switch to
165// C++23.
166template <typename Optional, typename Function,
167 typename Value = typename llvm::remove_cvref_t<Optional>::value_type>
168std::optional<std::invoke_result_t<Function, Value>>
169transformOptional(Optional &&O, Function &&F) {
170 if (O) {
171 return F(*std::forward<Optional>(O));
172 }
173 return std::nullopt;
174}
175
176/// Returns underlying integer value of an enum. Backport of C++23
177/// std::to_underlying.
178template <typename Enum>
179[[nodiscard]] constexpr std::underlying_type_t<Enum> to_underlying(Enum E) {
180 return static_cast<std::underlying_type_t<Enum>>(E);
181}
182
183// A tag for constructors accepting ranges.
185 explicit from_range_t() = default;
186};
187inline constexpr from_range_t from_range{};
188} // namespace llvm
189
190#endif // LLVM_ADT_STLFORWARDCOMPAT_H
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define F(x, y, z)
Definition MD5.cpp:54
#define T
#define P(N)
Mathematical constants.
constexpr T log10e_v
constexpr double sqrt2
constexpr double inv_sqrt2
constexpr T e_v
constexpr double inv_pi
constexpr T log2e_v
constexpr T egamma_v
constexpr T sqrt3_v
constexpr double ln2
constexpr double inv_sqrt3
constexpr double egamma
constexpr T sqrt2_v
constexpr T inv_sqrt3_v
constexpr T inv_sqrtpi_v
constexpr double ln10
constexpr double inv_sqrtpi
constexpr T ln10_v
constexpr double e
constexpr double phi
constexpr T pi_v
constexpr double sqrt3
constexpr T phi_v
constexpr double log10e
constexpr double log2e
constexpr T ln2_v
constexpr T inv_pi_v
constexpr T inv_sqrt2_v
constexpr double pi
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
constexpr from_range_t from_range
constexpr std::invoke_result_t< FnT, ArgsT... > invoke(FnT &&Fn, ArgsT &&...Args)
C++20 constexpr invoke.
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
DWARFExpression::Operation Op
auto to_address(const Ptr &P)
Returns a raw pointer that represents the same address as the argument.
typename detail::detector< void, Op, Args... >::value_t is_detected
Detects if a given trait holds for some set of arguments 'Args'.
std::optional< std::invoke_result_t< Function, Value > > transformOptional(Optional &&O, Function &&F)
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
from_range_t()=default
constexpr T && operator()(T &&self) const noexcept
std::remove_cv_t< std::remove_reference_t< T > > type