PageRenderTime 24ms CodeModel.GetById 16ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/3rd_party/llvm/include/llvm/ADT/Optional.h

https://code.google.com/p/softart/
C++ Header | 193 lines | 114 code | 23 blank | 56 comment | 12 complexity | 0a8f82188b0047033bdb72eb547243c2 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, JSON, MPL-2.0-no-copyleft-exception, GPL-2.0, GPL-3.0, LGPL-3.0, BSD-2-Clause
  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