Deleted Added
full compact
Optional.h (245431) Optional.h (252723)
1//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
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.
13//
14//===----------------------------------------------------------------------===//
15
1//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
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.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_ADT_OPTIONAL
17#define LLVM_ADT_OPTIONAL
16#ifndef LLVM_ADT_OPTIONAL_H
17#define LLVM_ADT_OPTIONAL_H
18
18
19#include "llvm/ADT/None.h"
19#include "llvm/Support/Compiler.h"
20#include "llvm/Support/Compiler.h"
21#include "llvm/Support/AlignOf.h"
20#include <cassert>
21
22#include <cassert>
23
22#if LLVM_USE_RVALUE_REFERENCES
24#if LLVM_HAS_RVALUE_REFERENCES
23#include <utility>
24#endif
25
26namespace llvm {
27
28template<typename T>
29class Optional {
25#include <utility>
26#endif
27
28namespace llvm {
29
30template<typename T>
31class Optional {
30 T x;
31 unsigned hasVal : 1;
32 AlignedCharArrayUnion<T> storage;
33 bool hasVal;
32public:
34public:
33 explicit Optional() : x(), hasVal(false) {}
34 Optional(const T &y) : x(y), hasVal(true) {}
35 Optional(NoneType) : hasVal(false) {}
36 explicit Optional() : hasVal(false) {}
37 Optional(const T &y) : hasVal(true) {
38 new (storage.buffer) T(y);
39 }
40 Optional(const Optional &O) : hasVal(O.hasVal) {
41 if (hasVal)
42 new (storage.buffer) T(*O);
43 }
35
44
36#if LLVM_USE_RVALUE_REFERENCES
37 Optional(T &&y) : x(std::forward<T>(y)), hasVal(true) {}
45#if LLVM_HAS_RVALUE_REFERENCES
46 Optional(T &&y) : hasVal(true) {
47 new (storage.buffer) T(std::forward<T>(y));
48 }
49 Optional(Optional<T> &&O) : hasVal(O) {
50 if (O) {
51 new (storage.buffer) T(std::move(*O));
52 O.reset();
53 }
54 }
55 Optional &operator=(T &&y) {
56 if (hasVal)
57 **this = std::move(y);
58 else {
59 new (storage.buffer) T(std::move(y));
60 hasVal = true;
61 }
62 return *this;
63 }
64 Optional &operator=(Optional &&O) {
65 if (!O)
66 reset();
67 else {
68 *this = std::move(*O);
69 O.reset();
70 }
71 return *this;
72 }
38#endif
39
40 static inline Optional create(const T* y) {
41 return y ? Optional(*y) : Optional();
42 }
43
73#endif
74
75 static inline Optional create(const T* y) {
76 return y ? Optional(*y) : Optional();
77 }
78
79 // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
80 // could be made more efficient by passing by value, possibly unifying them
81 // with the rvalue versions above - but this could place a different set of
82 // requirements (notably: the existence of a default ctor) when implemented
83 // in that way. Careful SFINAE to avoid such pitfalls would be required.
44 Optional &operator=(const T &y) {
84 Optional &operator=(const T &y) {
45 x = y;
46 hasVal = true;
85 if (hasVal)
86 **this = y;
87 else {
88 new (storage.buffer) T(y);
89 hasVal = true;
90 }
47 return *this;
48 }
91 return *this;
92 }
49
50 const T* getPointer() const { assert(hasVal); return &x; }
51 const T& getValue() const { assert(hasVal); return x; }
52
93
53 operator bool() const { return hasVal; }
94 Optional &operator=(const Optional &O) {
95 if (!O)
96 reset();
97 else
98 *this = *O;
99 return *this;
100 }
101
102 void reset() {
103 if (hasVal) {
104 (**this).~T();
105 hasVal = false;
106 }
107 }
108
109 ~Optional() {
110 reset();
111 }
112
113 const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
114 T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
115 const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
116 T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
117
118 LLVM_EXPLICIT operator bool() const { return hasVal; }
54 bool hasValue() const { return hasVal; }
55 const T* operator->() const { return getPointer(); }
119 bool hasValue() const { return hasVal; }
120 const T* operator->() const { return getPointer(); }
56 const T& operator*() const { assert(hasVal); return x; }
121 T* operator->() { return getPointer(); }
122 const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
123 T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
124
125#if LLVM_HAS_RVALUE_REFERENCE_THIS
126 T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
127 T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
128#endif
57};
58
129};
130
59template<typename T> struct simplify_type;
60
61template <typename T>
62struct simplify_type<const Optional<T> > {
63 typedef const T* SimpleType;
64 static SimpleType getSimplifiedValue(const Optional<T> &Val) {
65 return Val.getPointer();
66 }
131template <typename T> struct isPodLike;
132template <typename T> struct isPodLike<Optional<T> > {
133 // An Optional<T> is pod-like if T is.
134 static const bool value = isPodLike<T>::value;
67};
68
135};
136
69template <typename T>
70struct simplify_type<Optional<T> >
71 : public simplify_type<const Optional<T> > {};
72
73/// \brief Poison comparison between two \c Optional objects. Clients needs to
74/// explicitly compare the underlying values and account for empty \c Optional
75/// objects.
76///
137/// \brief Poison comparison between two \c Optional objects. Clients needs to
138/// explicitly compare the underlying values and account for empty \c Optional
139/// objects.
140///
77/// This routine will never be defined. It returns \c void to help diagnose
141/// This routine will never be defined. It returns \c void to help diagnose
78/// errors at compile time.
79template<typename T, typename U>
80void operator==(const Optional<T> &X, const Optional<U> &Y);
81
82/// \brief Poison comparison between two \c Optional objects. Clients needs to
83/// explicitly compare the underlying values and account for empty \c Optional
84/// objects.
85///
142/// errors at compile time.
143template<typename T, typename U>
144void operator==(const Optional<T> &X, const Optional<U> &Y);
145
146/// \brief Poison comparison between two \c Optional objects. Clients needs to
147/// explicitly compare the underlying values and account for empty \c Optional
148/// objects.
149///
86/// This routine will never be defined. It returns \c void to help diagnose
150/// This routine will never be defined. It returns \c void to help diagnose
87/// errors at compile time.
88template<typename T, typename U>
89void operator!=(const Optional<T> &X, const Optional<U> &Y);
90
91/// \brief Poison comparison between two \c Optional objects. Clients needs to
92/// explicitly compare the underlying values and account for empty \c Optional
93/// objects.
94///
151/// errors at compile time.
152template<typename T, typename U>
153void operator!=(const Optional<T> &X, const Optional<U> &Y);
154
155/// \brief Poison comparison between two \c Optional objects. Clients needs to
156/// explicitly compare the underlying values and account for empty \c Optional
157/// objects.
158///
95/// This routine will never be defined. It returns \c void to help diagnose
159/// This routine will never be defined. It returns \c void to help diagnose
96/// errors at compile time.
97template<typename T, typename U>
98void operator<(const Optional<T> &X, const Optional<U> &Y);
99
100/// \brief Poison comparison between two \c Optional objects. Clients needs to
101/// explicitly compare the underlying values and account for empty \c Optional
102/// objects.
103///
160/// errors at compile time.
161template<typename T, typename U>
162void operator<(const Optional<T> &X, const Optional<U> &Y);
163
164/// \brief Poison comparison between two \c Optional objects. Clients needs to
165/// explicitly compare the underlying values and account for empty \c Optional
166/// objects.
167///
104/// This routine will never be defined. It returns \c void to help diagnose
168/// This routine will never be defined. It returns \c void to help diagnose
105/// errors at compile time.
106template<typename T, typename U>
107void operator<=(const Optional<T> &X, const Optional<U> &Y);
108
109/// \brief Poison comparison between two \c Optional objects. Clients needs to
110/// explicitly compare the underlying values and account for empty \c Optional
111/// objects.
112///
169/// errors at compile time.
170template<typename T, typename U>
171void operator<=(const Optional<T> &X, const Optional<U> &Y);
172
173/// \brief Poison comparison between two \c Optional objects. Clients needs to
174/// explicitly compare the underlying values and account for empty \c Optional
175/// objects.
176///
113/// This routine will never be defined. It returns \c void to help diagnose
177/// This routine will never be defined. It returns \c void to help diagnose
114/// errors at compile time.
115template<typename T, typename U>
116void operator>=(const Optional<T> &X, const Optional<U> &Y);
117
118/// \brief Poison comparison between two \c Optional objects. Clients needs to
119/// explicitly compare the underlying values and account for empty \c Optional
120/// objects.
121///
178/// errors at compile time.
179template<typename T, typename U>
180void operator>=(const Optional<T> &X, const Optional<U> &Y);
181
182/// \brief Poison comparison between two \c Optional objects. Clients needs to
183/// explicitly compare the underlying values and account for empty \c Optional
184/// objects.
185///
122/// This routine will never be defined. It returns \c void to help diagnose
186/// This routine will never be defined. It returns \c void to help diagnose
123/// errors at compile time.
124template<typename T, typename U>
125void operator>(const Optional<T> &X, const Optional<U> &Y);
126
127} // end llvm namespace
128
129#endif
187/// errors at compile time.
188template<typename T, typename U>
189void operator>(const Optional<T> &X, const Optional<U> &Y);
190
191} // end llvm namespace
192
193#endif