Skip to content

Instantly share code, notes, and snippets.

@ecnelises
Last active November 23, 2016 17:12
Show Gist options
  • Save ecnelises/a13dfe63f16bccfa424a4ec4475a34ef to your computer and use it in GitHub Desktop.
Save ecnelises/a13dfe63f16bccfa424a4ec4475a34ef to your computer and use it in GitHub Desktop.
C++ Either类的简易实现
#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