Skip to content

Instantly share code, notes, and snippets.

@sean-parent
Created October 21, 2017 03:46
Show Gist options
  • Save sean-parent/d58594b7cc71be6dbdcaf1907dd17795 to your computer and use it in GitHub Desktop.
Save sean-parent/d58594b7cc71be6dbdcaf1907dd17795 to your computer and use it in GitHub Desktop.
#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;
}
@thecppzoo
Copy link

I think line 7 should be aligned to alignof(T):

     std::aligned_storage_t<sizeof(T), alignof(T)> _value;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment