Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- include/flang/Common/unwrap.h ---------------------------*- 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#ifndef FORTRAN_COMMON_UNWRAP_H_
10#define FORTRAN_COMMON_UNWRAP_H_
11
12#include "indirection.h"
13#include "reference-counted.h"
14#include "reference.h"
15#include "variant.h"
16#include "visit.h"
17#include <memory>
18#include <optional>
19#include <type_traits>
20
21// Given a nest of variants, optionals, &/or pointers, Unwrap<>() isolates
22// a packaged value of a specific type if it is present and returns a pointer
23// thereto; otherwise, it returns a null pointer. It's analogous to
24// std::get_if<>() but it accepts a reference argument and is recursive.
25// The target type parameter cannot be omitted.
26//
27// Be advised: If the target type parameter is not const-qualified, but the
28// isolated value is const-qualified, the result of Unwrap<> will be a
29// pointer to a const-qualified value.
30//
31// Further: const-qualified alternatives in instances of non-const-qualified
32// variants will not be returned from Unwrap if the target type is not
33// const-qualified.
34//
35// UnwrapCopy<>() is a variation of Unwrap<>() that returns an optional copy
36// of the value if one is present with the desired type.
37
38namespace Fortran::common {
39
40// Utility: Produces "const A" if B is const and A is not already so.
41template <typename A, typename B>
42using Constify = std::conditional_t<std::is_const_v<B> && !std::is_const_v<A>,
43 std::add_const_t<A>, A>;
44
45// Unwrap's mutually-recursive template functions are packaged in a struct
46// to avoid a need for prototypes.
47struct UnwrapperHelper {
48
49 // Base case
50 template <typename A, typename B>
51 static auto Unwrap(B &x) -> Constify<A, B> * {
52 if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) {
53 return &x;
54 } else {
55 return nullptr;
56 }
57 }
58
59 // Implementations of specializations
60 template <typename A, typename B>
61 static auto Unwrap(B *p) -> Constify<A, B> * {
62 if (p) {
63 return Unwrap<A>(*p);
64 } else {
65 return nullptr;
66 }
67 }
68
69 template <typename A, typename B>
70 static auto Unwrap(const std::unique_ptr<B> &p) -> Constify<A, B> * {
71 if (p.get()) {
72 return Unwrap<A>(*p);
73 } else {
74 return nullptr;
75 }
76 }
77
78 template <typename A, typename B>
79 static auto Unwrap(const std::shared_ptr<B> &p) -> Constify<A, B> * {
80 if (p.get()) {
81 return Unwrap<A>(*p);
82 } else {
83 return nullptr;
84 }
85 }
86
87 template <typename A, typename B>
88 static auto Unwrap(std::optional<B> &x) -> Constify<A, B> * {
89 if (x) {
90 return Unwrap<A>(*x);
91 } else {
92 return nullptr;
93 }
94 }
95
96 template <typename A, typename B>
97 static auto Unwrap(const std::optional<B> &x) -> Constify<A, B> * {
98 if (x) {
99 return Unwrap<A>(*x);
100 } else {
101 return nullptr;
102 }
103 }
104
105 template <typename A, typename... Bs>
106 static A *Unwrap(std::variant<Bs...> &u) {
107 return common::visit(
108 [](auto &x) -> A * {
109 using Ty = std::decay_t<decltype(Unwrap<A>(x))>;
110 if constexpr (!std::is_const_v<std::remove_pointer_t<Ty>> ||
111 std::is_const_v<A>) {
112 return Unwrap<A>(x);
113 }
114 return nullptr;
115 },
116 u);
117 }
118
119 template <typename A, typename... Bs>
120 static auto Unwrap(const std::variant<Bs...> &u) -> std::add_const_t<A> * {
121 return common::visit(
122 [](const auto &x) -> std::add_const_t<A> * { return Unwrap<A>(x); }, u);
123 }
124
125 template <typename A, typename B>
126 static auto Unwrap(const Reference<B> &ref) -> Constify<A, B> * {
127 return Unwrap<A>(*ref);
128 }
129
130 template <typename A, typename B, bool COPY>
131 static auto Unwrap(const Indirection<B, COPY> &p) -> Constify<A, B> * {
132 return Unwrap<A>(p.value());
133 }
134
135 template <typename A, typename B>
136 static auto Unwrap(const CountedReference<B> &p) -> Constify<A, B> * {
137 if (p.get()) {
138 return Unwrap<A>(*p);
139 } else {
140 return nullptr;
141 }
142 }
143};
144
145template <typename A, typename B> auto Unwrap(B &x) -> Constify<A, B> * {
146 return UnwrapperHelper::Unwrap<A>(x);
147}
148
149// Returns a copy of a wrapped value, if present, otherwise a vacant optional.
150template <typename A, typename B> std::optional<A> UnwrapCopy(const B &x) {
151 if (const A * p{Unwrap<A>(x)}) {
152 return std::make_optional<A>(*p);
153 } else {
154 return std::nullopt;
155 }
156}
157} // namespace Fortran::common
158#endif // FORTRAN_COMMON_UNWRAP_H_
159

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Common/unwrap.h