Several improvements to the Either<T,U> type

llvm-svn: 243053
This commit is contained in:
Enrico Granata 2015-07-23 22:17:39 +00:00
parent d9c1bc9955
commit fe563d5573
1 changed files with 91 additions and 9 deletions

View File

@ -12,36 +12,56 @@
#include "llvm/ADT/Optional.h"
#include <functional>
namespace lldb_utility {
template <typename T1, typename T2>
class Either {
class Either
{
private:
enum class Selected {
enum class Selected
{
One, Two
};
Selected m_selected;
union {
union
{
T1 m_t1;
T2 m_t2;
};
public:
Either(const T1& t1)
Either (const T1& t1)
{
m_t1 = t1;
m_selected = Selected::One;
}
Either(const T2& t2)
Either (const T2& t2)
{
m_t2 = t2;
m_selected = Selected::Two;
}
template <class X, typename std::enable_if<std::is_same<T1,X>::value>::type * = nullptr >
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()
GetAs() const
{
switch (m_selected)
{
@ -52,9 +72,9 @@ namespace lldb_utility {
}
}
template <class X, typename std::enable_if<std::is_same<T2,X>::value>::type * = nullptr >
template <class X, typename std::enable_if<std::is_same<T2,X>::value>::type * = nullptr>
llvm::Optional<T2>
GetAs()
GetAs() const
{
switch (m_selected)
{
@ -64,6 +84,68 @@ namespace lldb_utility {
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