Skip to content

Instantly share code, notes, and snippets.

@hzhangxyz
Last active September 24, 2019 09:26
Show Gist options
  • Save hzhangxyz/7bcb28fb62bc39c8bb0285f2ae7f2409 to your computer and use it in GitHub Desktop.
Save hzhangxyz/7bcb28fb62bc39c8bb0285f2ae7f2409 to your computer and use it in GitHub Desktop.
use variant like julia union
#include <iostream>
#include <random>
#include <type_traits>
#include <variant>
template <class T> struct replace_void { using type = T; };
template <> struct replace_void<void> { using type = std::monostate; };
template <class T> using replace_void_t = typename replace_void<T>::type;
template <class... Fn> struct overloaded : Fn... {
using Fn::operator()...;
template <class... T>
auto operator()(std::variant<std::monostate, T...> arg) {
using Res =
std::variant<std::monostate,
replace_void_t<std::invoke_result_t<overloaded, T>>...>;
auto res = Res();
auto try_set = [&]<class S>() {
using R = std::invoke_result_t<overloaded, S>;
if constexpr (std::is_void_v<R>) {
this->operator()(std::get<S>(arg));
} else {
res = Res(this->operator()(std::get<S>(arg)));
}
return true;
};
((std::holds_alternative<T>(arg) && try_set.template operator()<T>()), ...);
return res;
}
};
template <class... Fn> overloaded(Fn...)->overloaded<Fn...>;
int main() {
auto e = std::default_random_engine(std::random_device()());
auto d = std::uniform_real_distribution<double>(0, 1);
using tp = std::variant<std::monostate, double, int>;
auto p = tp();
if (auto v = d(e); v > 0.5) {
p = v;
} else {
p = static_cast<int>(v * 1000);
}
auto f =
overloaded{[](int p) { std::cout << "v :: int = " << p << "\n"; return double(p);},
[](double p) { std::cout << "v :: double = " << p << "\n"; return int(p*1000);}};
auto g =
overloaded{[](int p) { std::cout << "w :: int = " << p << "\n"; },
[](double p) { std::cout << "w :: double = " << p << "\n"; }};
g(f(p));
return 0;
}
function f(p::Int64)
print("v :: int = $p\n");
return Float64(p);
end
function f(p::Float64)
print("v :: double = $p\n");
return Int64(floor(p*1000));
end
function g(p::Int64)
print("w :: int = $p\n");
end
function g(p::Float64)
print("w :: double = $p\n");
end
p = rand()
if p < 0.5
p = Int64(floor(p*1000))
end
g(f(p))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment