Created
October 21, 2017 03:46
-
-
Save sean-parent/d58594b7cc71be6dbdcaf1907dd17795 to your computer and use it in GitHub Desktop.
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
#include <functional> | |
#include <iostream> | |
#include <string> | |
template <class T> | |
class maybe { | |
std::aligned_storage_t<sizeof(T)> _value; | |
bool _has_value = false; | |
public: | |
maybe() = default; | |
template <class U> | |
static auto unit(U&& x) { | |
return maybe<std::decay_t<U>>(std::forward<U>(x)); | |
} | |
template <class... Args> | |
maybe(Args&&... args) { | |
new (&_value) T(args...); | |
_has_value = true; | |
} | |
maybe(const maybe& mx) { | |
mx | [&](auto x) { | |
new (&_value) T(x); | |
_has_value = true; | |
}; | |
} | |
maybe(maybe&& mx) noexcept { | |
mx | [&](auto& x) { | |
new (&_value) T(std::move(x)); | |
_has_value = true; | |
}; | |
} | |
template <class G> | |
friend auto operator|(const maybe& m, G&& g) { | |
if (m._has_value) | |
return std::forward<G>(g)(*static_cast<const T*>(static_cast<const void*>(&m._value))); | |
return std::result_of_t<std::decay_t<G>(T)>(); | |
} | |
template <class G> | |
friend auto operator|(maybe&& m, G&& g) { | |
if (m._has_value) | |
return std::forward<G>(g)(std::move(*static_cast<T*>(static_cast<void*>(&m._value)))); | |
return std::result_of_t<std::decay_t<G>(T)>(); | |
} | |
}; | |
template <class F, class M> | |
auto fmap(F&& f, M&& m) { | |
return m | [&](auto&& x) { | |
return std::decay_t<M>::unit(std::forward<F>(f)(std::forward<decltype(x)>(x))); | |
}; | |
} | |
template <class M> | |
auto join(M&& m) { | |
return m | [](auto&& x) { return x; }; | |
} | |
maybe<int> operator+(const maybe<int>& mx, const maybe<int>& my) { | |
return mx | [&](int x) { return my | [&](int y) { return maybe<int>(x + y); }; }; | |
} | |
int main() { | |
using namespace std::string_literals; | |
maybe<int> x = 10; | |
maybe<int> y = 20; | |
fmap([](int x) { return (x == 10) ? "success"s : "fail"s; }, x) | | |
[](const std::string& r) { std::cout << r << std::endl; }; | |
(x + y) | [](int r) { std::cout << r << std::endl; }; | |
std::cout << join(x + x + y) << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think line 7 should be aligned to
alignof(T)
: