| //===-- 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_ |