]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Utility/Either.h
MFC r345703:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Utility / Either.h
1 //===-- Either.h -----------------------------------------------*- 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 #ifndef liblldb_Either_h_
11 #define liblldb_Either_h_
12
13 #include "llvm/ADT/Optional.h"
14
15 #include <functional>
16
17 namespace lldb_utility {
18 template <typename T1, typename T2> class Either {
19 private:
20   enum class Selected { One, Two };
21
22   Selected m_selected;
23   union {
24     T1 m_t1;
25     T2 m_t2;
26   };
27
28 public:
29   Either(const T1 &t1) {
30     m_t1 = t1;
31     m_selected = Selected::One;
32   }
33
34   Either(const T2 &t2) {
35     m_t2 = t2;
36     m_selected = Selected::Two;
37   }
38
39   Either(const Either<T1, T2> &rhs) {
40     switch (rhs.m_selected) {
41     case Selected::One:
42       m_t1 = rhs.GetAs<T1>().getValue();
43       m_selected = Selected::One;
44       break;
45     case Selected::Two:
46       m_t2 = rhs.GetAs<T2>().getValue();
47       m_selected = Selected::Two;
48       break;
49     }
50   }
51
52   template <class X, typename std::enable_if<std::is_same<T1, X>::value>::type
53                          * = nullptr>
54   llvm::Optional<T1> GetAs() const {
55     switch (m_selected) {
56     case Selected::One:
57       return m_t1;
58     default:
59       return llvm::Optional<T1>();
60     }
61   }
62
63   template <class X, typename std::enable_if<std::is_same<T2, X>::value>::type
64                          * = nullptr>
65   llvm::Optional<T2> GetAs() const {
66     switch (m_selected) {
67     case Selected::Two:
68       return m_t2;
69     default:
70       return llvm::Optional<T2>();
71     }
72   }
73
74   template <class ResultType>
75   ResultType Apply(std::function<ResultType(T1)> if_T1,
76                    std::function<ResultType(T2)> if_T2) const {
77     switch (m_selected) {
78     case Selected::One:
79       return if_T1(m_t1);
80     case Selected::Two:
81       return if_T2(m_t2);
82     }
83   }
84
85   bool operator==(const Either<T1, T2> &rhs) {
86     return (GetAs<T1>() == rhs.GetAs<T1>()) && (GetAs<T2>() == rhs.GetAs<T2>());
87   }
88
89   explicit operator bool() {
90     switch (m_selected) {
91     case Selected::One:
92       return (bool)m_t1;
93     case Selected::Two:
94       return (bool)m_t2;
95     }
96   }
97
98   Either<T1, T2> &operator=(const Either<T1, T2> &rhs) {
99     switch (rhs.m_selected) {
100     case Selected::One:
101       m_t1 = rhs.GetAs<T1>().getValue();
102       m_selected = Selected::One;
103       break;
104     case Selected::Two:
105       m_t2 = rhs.GetAs<T2>().getValue();
106       m_selected = Selected::Two;
107       break;
108     }
109     return *this;
110   }
111
112   ~Either() {
113     switch (m_selected) {
114     case Selected::One:
115       m_t1.T1::~T1();
116       break;
117     case Selected::Two:
118       m_t2.T2::~T2();
119       break;
120     }
121   }
122 };
123
124 } // namespace lldb_utility
125
126 #endif // #ifndef liblldb_Either_h_