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_H
17#define LLVM_ADT_OPTIONAL_H
18
19#include "llvm/ADT/None.h"
20#include "llvm/Support/Compiler.h"
21#include "llvm/Support/AlignOf.h"
22#include <cassert>
23
24#if LLVM_HAS_RVALUE_REFERENCES
25#include <utility>
26#endif
27
28namespace llvm {
29
30template<typename T>
31class Optional {
32  AlignedCharArrayUnion<T> storage;
33  bool hasVal;
34public:
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  }
44
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  }
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.
84  Optional &operator=(const T &y) {
85    if (hasVal)
86      **this = y;
87    else {
88      new (storage.buffer) T(y);
89      hasVal = true;
90    }
91    return *this;
92  }
93
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; }
119  bool hasValue() const { return hasVal; }
120  const T* operator->() const { return getPointer(); }
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
129};
130
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;
135};
136
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///
141/// This routine will never be defined. It returns \c void to help diagnose
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///
150/// This routine will never be defined. It returns \c void to help diagnose
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///
159/// This routine will never be defined. It returns \c void to help diagnose
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///
168/// This routine will never be defined. It returns \c void to help diagnose
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///
177/// This routine will never be defined. It returns \c void to help diagnose
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///
186/// This routine will never be defined. It returns \c void to help diagnose
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
194