]>
git.proxmox.com Git - rustc.git/blob - src/llvm/include/llvm/ADT/Optional.h
1 //===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file provides Optional, a template class modeled in the spirit of
11 // OCaml's 'opt' variant. The idea is to strongly type whether or not
12 // a value can be optional.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_ADT_OPTIONAL_H
17 #define LLVM_ADT_OPTIONAL_H
19 #include "llvm/ADT/None.h"
20 #include "llvm/Support/AlignOf.h"
21 #include "llvm/Support/Compiler.h"
30 AlignedCharArrayUnion
<T
> storage
;
35 Optional(NoneType
) : hasVal(false) {}
36 explicit Optional() : hasVal(false) {}
37 Optional(const T
&y
) : hasVal(true) {
38 new (storage
.buffer
) T(y
);
40 Optional(const Optional
&O
) : hasVal(O
.hasVal
) {
42 new (storage
.buffer
) T(*O
);
45 Optional(T
&&y
) : hasVal(true) {
46 new (storage
.buffer
) T(std::forward
<T
>(y
));
48 Optional(Optional
<T
> &&O
) : hasVal(O
) {
50 new (storage
.buffer
) T(std::move(*O
));
54 Optional
&operator=(T
&&y
) {
56 **this = std::move(y
);
58 new (storage
.buffer
) T(std::move(y
));
63 Optional
&operator=(Optional
&&O
) {
67 *this = std::move(*O
);
73 #if LLVM_HAS_VARIADIC_TEMPLATES
75 /// Create a new object by constructing it in place with the given arguments.
76 template<typename
...ArgTypes
>
77 void emplace(ArgTypes
&&...Args
) {
80 new (storage
.buffer
) T(std::forward
<ArgTypes
>(Args
)...);
85 /// Create a new object by default-constructing it in place.
89 new (storage
.buffer
) T();
92 /// Create a new object by constructing it in place with the given arguments.
94 void emplace(T1
&&A1
) {
97 new (storage
.buffer
) T(std::forward
<T1
>(A1
));
100 /// Create a new object by constructing it in place with the given arguments.
101 template<typename T1
, typename T2
>
102 void emplace(T1
&&A1
, T2
&&A2
) {
105 new (storage
.buffer
) T(std::forward
<T1
>(A1
), std::forward
<T2
>(A2
));
108 /// Create a new object by constructing it in place with the given arguments.
109 template<typename T1
, typename T2
, typename T3
>
110 void emplace(T1
&&A1
, T2
&&A2
, T3
&&A3
) {
113 new (storage
.buffer
) T(std::forward
<T1
>(A1
), std::forward
<T2
>(A2
),
114 std::forward
<T3
>(A3
));
117 /// Create a new object by constructing it in place with the given arguments.
118 template<typename T1
, typename T2
, typename T3
, typename T4
>
119 void emplace(T1
&&A1
, T2
&&A2
, T3
&&A3
, T4
&&A4
) {
122 new (storage
.buffer
) T(std::forward
<T1
>(A1
), std::forward
<T2
>(A2
),
123 std::forward
<T3
>(A3
), std::forward
<T4
>(A4
));
126 #endif // LLVM_HAS_VARIADIC_TEMPLATES
128 static inline Optional
create(const T
* y
) {
129 return y
? Optional(*y
) : Optional();
132 // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
133 // could be made more efficient by passing by value, possibly unifying them
134 // with the rvalue versions above - but this could place a different set of
135 // requirements (notably: the existence of a default ctor) when implemented
136 // in that way. Careful SFINAE to avoid such pitfalls would be required.
137 Optional
&operator=(const T
&y
) {
141 new (storage
.buffer
) T(y
);
147 Optional
&operator=(const Optional
&O
) {
166 const T
* getPointer() const { assert(hasVal
); return reinterpret_cast<const T
*>(storage
.buffer
); }
167 T
* getPointer() { assert(hasVal
); return reinterpret_cast<T
*>(storage
.buffer
); }
168 const T
& getValue() const LLVM_LVALUE_FUNCTION
{ assert(hasVal
); return *getPointer(); }
169 T
& getValue() LLVM_LVALUE_FUNCTION
{ assert(hasVal
); return *getPointer(); }
171 LLVM_EXPLICIT
operator bool() const { return hasVal
; }
172 bool hasValue() const { return hasVal
; }
173 const T
* operator->() const { return getPointer(); }
174 T
* operator->() { return getPointer(); }
175 const T
& operator*() const LLVM_LVALUE_FUNCTION
{ assert(hasVal
); return *getPointer(); }
176 T
& operator*() LLVM_LVALUE_FUNCTION
{ assert(hasVal
); return *getPointer(); }
178 template <typename U
>
179 LLVM_CONSTEXPR T
getValueOr(U
&&value
) const LLVM_LVALUE_FUNCTION
{
180 return hasValue() ? getValue() : std::forward
<U
>(value
);
183 #if LLVM_HAS_RVALUE_REFERENCE_THIS
184 T
&& getValue() && { assert(hasVal
); return std::move(*getPointer()); }
185 T
&& operator*() && { assert(hasVal
); return std::move(*getPointer()); }
187 template <typename U
>
188 T
getValueOr(U
&&value
) && {
189 return hasValue() ? std::move(getValue()) : std::forward
<U
>(value
);
194 template <typename T
> struct isPodLike
;
195 template <typename T
> struct isPodLike
<Optional
<T
> > {
196 // An Optional<T> is pod-like if T is.
197 static const bool value
= isPodLike
<T
>::value
;
200 /// \brief Poison comparison between two \c Optional objects. Clients needs to
201 /// explicitly compare the underlying values and account for empty \c Optional
204 /// This routine will never be defined. It returns \c void to help diagnose
205 /// errors at compile time.
206 template<typename T
, typename U
>
207 void operator==(const Optional
<T
> &X
, const Optional
<U
> &Y
);
209 /// \brief Poison comparison between two \c Optional objects. Clients needs to
210 /// explicitly compare the underlying values and account for empty \c Optional
213 /// This routine will never be defined. It returns \c void to help diagnose
214 /// errors at compile time.
215 template<typename T
, typename U
>
216 void operator!=(const Optional
<T
> &X
, const Optional
<U
> &Y
);
218 /// \brief Poison comparison between two \c Optional objects. Clients needs to
219 /// explicitly compare the underlying values and account for empty \c Optional
222 /// This routine will never be defined. It returns \c void to help diagnose
223 /// errors at compile time.
224 template<typename T
, typename U
>
225 void operator<(const Optional
<T
> &X
, const Optional
<U
> &Y
);
227 /// \brief Poison comparison between two \c Optional objects. Clients needs to
228 /// explicitly compare the underlying values and account for empty \c Optional
231 /// This routine will never be defined. It returns \c void to help diagnose
232 /// errors at compile time.
233 template<typename T
, typename U
>
234 void operator<=(const Optional
<T
> &X
, const Optional
<U
> &Y
);
236 /// \brief Poison comparison between two \c Optional objects. Clients needs to
237 /// explicitly compare the underlying values and account for empty \c Optional
240 /// This routine will never be defined. It returns \c void to help diagnose
241 /// errors at compile time.
242 template<typename T
, typename U
>
243 void operator>=(const Optional
<T
> &X
, const Optional
<U
> &Y
);
245 /// \brief Poison comparison between two \c Optional objects. Clients needs to
246 /// explicitly compare the underlying values and account for empty \c Optional
249 /// This routine will never be defined. It returns \c void to help diagnose
250 /// errors at compile time.
251 template<typename T
, typename U
>
252 void operator>(const Optional
<T
> &X
, const Optional
<U
> &Y
);
254 } // end llvm namespace