blob: 0dc340b64e86a74a37b32c7ea17fb24d5f679de6 [file] [log] [blame]
//===-- 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_