diff options
Diffstat (limited to 'include/lldb/Utility/Either.h')
-rw-r--r-- | include/lldb/Utility/Either.h | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/include/lldb/Utility/Either.h b/include/lldb/Utility/Either.h new file mode 100644 index 000000000000..ae647363512d --- /dev/null +++ b/include/lldb/Utility/Either.h @@ -0,0 +1,154 @@ +//===-- Either.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Either_h_ +#define liblldb_Either_h_ + +#include "llvm/ADT/Optional.h" + +#include <functional> + +namespace lldb_utility { + template <typename T1, typename T2> + class Either + { + private: + enum class Selected + { + One, Two + }; + + Selected m_selected; + union + { + T1 m_t1; + T2 m_t2; + }; + + public: + Either (const T1& t1) + { + m_t1 = t1; + m_selected = Selected::One; + } + + Either (const T2& t2) + { + m_t2 = t2; + m_selected = Selected::Two; + } + + Either (const Either<T1,T2>& rhs) + { + switch (rhs.m_selected) + { + case Selected::One: + m_t1 = rhs.GetAs<T1>().getValue(); + m_selected = Selected::One; + break; + case Selected::Two: + m_t2 = rhs.GetAs<T2>().getValue(); + m_selected = Selected::Two; + break; + } + } + + template <class X, typename std::enable_if<std::is_same<T1,X>::value>::type * = nullptr> + llvm::Optional<T1> + GetAs() const + { + switch (m_selected) + { + case Selected::One: + return m_t1; + default: + return llvm::Optional<T1>(); + } + } + + template <class X, typename std::enable_if<std::is_same<T2,X>::value>::type * = nullptr> + llvm::Optional<T2> + GetAs() const + { + switch (m_selected) + { + case Selected::Two: + return m_t2; + default: + return llvm::Optional<T2>(); + } + } + + template <class ResultType> + ResultType + Apply (std::function<ResultType(T1)> if_T1, + std::function<ResultType(T2)> if_T2) const + { + switch (m_selected) + { + case Selected::One: + return if_T1(m_t1); + case Selected::Two: + return if_T2(m_t2); + } + } + + bool + operator == (const Either<T1,T2>& rhs) + { + return (GetAs<T1>() == rhs.GetAs<T1>()) && (GetAs<T2>() == rhs.GetAs<T2>()); + } + + explicit + operator bool () + { + switch (m_selected) + { + case Selected::One: + return (bool)m_t1; + case Selected::Two: + return (bool)m_t2; + } + } + + Either<T1,T2>& + operator = (const Either<T1,T2>& rhs) + { + switch (rhs.m_selected) + { + case Selected::One: + m_t1 = rhs.GetAs<T1>().getValue(); + m_selected = Selected::One; + break; + case Selected::Two: + m_t2 = rhs.GetAs<T2>().getValue(); + m_selected = Selected::Two; + break; + } + return *this; + } + + ~Either () + { + switch (m_selected) + { + case Selected::One: + m_t1.T1::~T1(); + break; + case Selected::Two: + m_t2.T2::~T2(); + break; + } + } + }; + +} // namespace lldb_utility + +#endif // #ifndef liblldb_Either_h_ + |