Skip to content

Instantly share code, notes, and snippets.

@technic
Created August 22, 2021 21:42
Show Gist options
  • Save technic/cef74a9a2d6385aa44877b09830d140f to your computer and use it in GitHub Desktop.
Save technic/cef74a9a2d6385aa44877b09830d140f to your computer and use it in GitHub Desktop.
#include <variant>
#include <type_traits>
#include <iostream>
#include <string>
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
template<typename T>
struct wrapper {
using value_t = T;
T value;
};
template<typename T, typename F>
struct as_impl {
using value_t = typename T::value_t;
as_impl(F && f) : f(std::move(f)) {}
auto operator()(T arg) { return f(arg.value); }
F f;
};
template<typename T>
struct as {
as() = default;
template<typename F>
auto operator=(F && f) requires(std::is_invocable_v<F, typename T::value_t>) {
return as_impl<T, F>(std::forward<F>(f));
}
};
//
struct foo : wrapper<std::string> {};
struct bar : wrapper<int> {};
struct baz : wrapper<int> {};
[[gnu::noinline]]
void test(const std::variant<bar, baz, foo> &v) {
std::visit(overloaded {
as<bar>() = [](int x) {
std::cout << "bar " << x << std::endl;
},
as<baz>() = [](int x) {
std::cout << "baz " << x << std::endl;
},
as<foo>() = [](auto s) {
std::cout << "sss " << s << std::endl;
}
}, v);
}
int main() {
test(bar{10});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment