Last active
November 23, 2016 17:12
-
-
Save ecnelises/a13dfe63f16bccfa424a4ec4475a34ef to your computer and use it in GitHub Desktop.
C++ Either类的简易实现
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef EITHER_HPP | |
#define EITHER_HPP | |
#include <type_traits> | |
template<typename T1, typename T2> | |
struct MaxTypeSizeHelper { | |
const static auto size = (sizeof(T1) > sizeof(T2)) ? sizeof(T1) : sizeof(T2); | |
}; | |
template<typename Left, typename Right> | |
class Either { | |
public: | |
Either(void) = delete; | |
Either(const Left& val) : is_left(true) | |
{ | |
new (&data) Left(val); | |
} | |
Either(const Right& val) : is_left(false) | |
{ | |
new (&data) Right(val); | |
} | |
Either(const Either& another) : is_left(another.is_left) | |
{ | |
if (is_left) { | |
new (&data) Left(*((Left*)&(another.data))); | |
} else { | |
new (&data) Right(*((Right*)&(another.data))); | |
} | |
} | |
Either(Either&& another) : Either(another) {} | |
~Either() | |
{ | |
if (is_left) { | |
((Left*)(&data))->~Left(); | |
} else { | |
((Right*)(&data))->~Right(); | |
} | |
} | |
template<typename F> | |
Either& caseLeft(F func) | |
{ | |
if (is_left) { | |
func(*((Left*)&data)); | |
} | |
return *this; | |
} | |
template<typename F> | |
Either& caseRight(F func) | |
{ | |
if (!is_left) { | |
func(*((Right*)&data)); | |
} | |
return *this; | |
} | |
bool isLeft(void) | |
{ | |
return is_left; | |
} | |
bool isRight(void) | |
{ | |
return !is_left; | |
} | |
private: | |
bool is_left; | |
typename std::aligned_storage<MaxTypeSizeHelper<Left, Right>::size>::type data; | |
}; | |
#endif // EITHER_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment