LLVM API Documentation

Optional.h
Go to the documentation of this file.
00001 //===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file provides Optional, a template class modeled in the spirit of
00011 //  OCaml's 'opt' variant.  The idea is to strongly type whether or not
00012 //  a value can be optional.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #ifndef LLVM_ADT_OPTIONAL_H
00017 #define LLVM_ADT_OPTIONAL_H
00018 
00019 #include "llvm/ADT/None.h"
00020 #include "llvm/Support/AlignOf.h"
00021 #include "llvm/Support/Compiler.h"
00022 #include <cassert>
00023 #include <utility>
00024 
00025 namespace llvm {
00026 
00027 template<typename T>
00028 class Optional {
00029   AlignedCharArrayUnion<T> storage;
00030   bool hasVal;
00031 public:
00032   Optional(NoneType) : hasVal(false) {}
00033   explicit Optional() : hasVal(false) {}
00034   Optional(const T &y) : hasVal(true) {
00035     new (storage.buffer) T(y);
00036   }
00037   Optional(const Optional &O) : hasVal(O.hasVal) {
00038     if (hasVal)
00039       new (storage.buffer) T(*O);
00040   }
00041 
00042   Optional(T &&y) : hasVal(true) {
00043     new (storage.buffer) T(std::forward<T>(y));
00044   }
00045   Optional(Optional<T> &&O) : hasVal(O) {
00046     if (O) {
00047       new (storage.buffer) T(std::move(*O));
00048       O.reset();
00049     }
00050   }
00051   Optional &operator=(T &&y) {
00052     if (hasVal)
00053       **this = std::move(y);
00054     else {
00055       new (storage.buffer) T(std::move(y));
00056       hasVal = true;
00057     }
00058     return *this;
00059   }
00060   Optional &operator=(Optional &&O) {
00061     if (!O)
00062       reset();
00063     else {
00064       *this = std::move(*O);
00065       O.reset();
00066     }
00067     return *this;
00068   }
00069 
00070   static inline Optional create(const T* y) {
00071     return y ? Optional(*y) : Optional();
00072   }
00073 
00074   // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
00075   // could be made more efficient by passing by value, possibly unifying them
00076   // with the rvalue versions above - but this could place a different set of
00077   // requirements (notably: the existence of a default ctor) when implemented
00078   // in that way. Careful SFINAE to avoid such pitfalls would be required.
00079   Optional &operator=(const T &y) {
00080     if (hasVal)
00081       **this = y;
00082     else {
00083       new (storage.buffer) T(y);
00084       hasVal = true;
00085     }
00086     return *this;
00087   }
00088 
00089   Optional &operator=(const Optional &O) {
00090     if (!O)
00091       reset();
00092     else
00093       *this = *O;
00094     return *this;
00095   }
00096 
00097   void reset() {
00098     if (hasVal) {
00099       (**this).~T();
00100       hasVal = false;
00101     }
00102   }
00103 
00104   ~Optional() {
00105     reset();
00106   }
00107 
00108   const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
00109   T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
00110   const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
00111   T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
00112 
00113   LLVM_EXPLICIT operator bool() const { return hasVal; }
00114   bool hasValue() const { return hasVal; }
00115   const T* operator->() const { return getPointer(); }
00116   T* operator->() { return getPointer(); }
00117   const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
00118   T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
00119 
00120 #if LLVM_HAS_RVALUE_REFERENCE_THIS
00121   T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
00122   T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
00123 #endif
00124 };
00125 
00126 template <typename T> struct isPodLike;
00127 template <typename T> struct isPodLike<Optional<T> > {
00128   // An Optional<T> is pod-like if T is.
00129   static const bool value = isPodLike<T>::value;
00130 };
00131 
00132 /// \brief Poison comparison between two \c Optional objects. Clients needs to
00133 /// explicitly compare the underlying values and account for empty \c Optional
00134 /// objects.
00135 ///
00136 /// This routine will never be defined. It returns \c void to help diagnose
00137 /// errors at compile time.
00138 template<typename T, typename U>
00139 void operator==(const Optional<T> &X, const Optional<U> &Y);
00140 
00141 /// \brief Poison comparison between two \c Optional objects. Clients needs to
00142 /// explicitly compare the underlying values and account for empty \c Optional
00143 /// objects.
00144 ///
00145 /// This routine will never be defined. It returns \c void to help diagnose
00146 /// errors at compile time.
00147 template<typename T, typename U>
00148 void operator!=(const Optional<T> &X, const Optional<U> &Y);
00149 
00150 /// \brief Poison comparison between two \c Optional objects. Clients needs to
00151 /// explicitly compare the underlying values and account for empty \c Optional
00152 /// objects.
00153 ///
00154 /// This routine will never be defined. It returns \c void to help diagnose
00155 /// errors at compile time.
00156 template<typename T, typename U>
00157 void operator<(const Optional<T> &X, const Optional<U> &Y);
00158 
00159 /// \brief Poison comparison between two \c Optional objects. Clients needs to
00160 /// explicitly compare the underlying values and account for empty \c Optional
00161 /// objects.
00162 ///
00163 /// This routine will never be defined. It returns \c void to help diagnose
00164 /// errors at compile time.
00165 template<typename T, typename U>
00166 void operator<=(const Optional<T> &X, const Optional<U> &Y);
00167 
00168 /// \brief Poison comparison between two \c Optional objects. Clients needs to
00169 /// explicitly compare the underlying values and account for empty \c Optional
00170 /// objects.
00171 ///
00172 /// This routine will never be defined. It returns \c void to help diagnose
00173 /// errors at compile time.
00174 template<typename T, typename U>
00175 void operator>=(const Optional<T> &X, const Optional<U> &Y);
00176 
00177 /// \brief Poison comparison between two \c Optional objects. Clients needs to
00178 /// explicitly compare the underlying values and account for empty \c Optional
00179 /// objects.
00180 ///
00181 /// This routine will never be defined. It returns \c void to help diagnose
00182 /// errors at compile time.
00183 template<typename T, typename U>
00184 void operator>(const Optional<T> &X, const Optional<U> &Y);
00185 
00186 } // end llvm namespace
00187 
00188 #endif