Skip to content

Instantly share code, notes, and snippets.

@dgodfrey206
Created February 21, 2026 06:13
Show Gist options
  • Select an option

  • Save dgodfrey206/64edd4246fe4ed01f7711521bce5c0d9 to your computer and use it in GitHub Desktop.

Select an option

Save dgodfrey206/64edd4246fe4ed01f7711521bce5c0d9 to your computer and use it in GitHub Desktop.
#include <any>
#include <print>
#include <string>
#include <type_traits>
using namespace std;
#pragma GCC diagnostic ignored "-Wnon-template-friend"
template <class T, class... Ts>
class A : A<Ts...> {
public:
A(T&& t, Ts&&... ts) :
A<Ts...>(std::forward<Ts>(ts)...),
t(std::forward<T>(t)) {}
template <class F>
void visit(F f) {
if constexpr (std::is_invocable_v<F, T>) {
f(t);
}
A<Ts...>::visit(f);
}
T t;
};
template <class T>
class A<T> {
public:
template <class F>
void visit(F f) {
if constexpr (std::is_invocable_v<F, T>) {
f(t);
}
}
T t;
};
// Source - https://stackoverflow.com/a/70701479
// Posted by HolyBlackCat (Modified slightly)
// Retrieved 2026-02-20, License - CC BY-SA 4.0
namespace detail
{
template<class T>
struct Reader
{
friend auto adl_GetType(Reader<T>);
};
template<class T, class U>
struct Writer
{
friend auto adl_GetType(Reader<T>){return U{};}
};
inline void adl_GetType() {}
template<class T>
using Read = std::remove_pointer_t<decltype(adl_GetType(Reader<T>{}))>;
}
class Wrapper {
struct type_tag {};
template<class...Ts>
static constexpr auto inject_adl_definition() -> decltype(detail::Writer<type_tag, A<Ts...>*>{}, void()) {}
// The conditional is used so that F is a dependent type to prevent instantiation before visit is called
template<class F, class T>
using variant_type = std::conditional_t<false, F, detail::Read<T>>;
public:
template <class... Args>
Wrapper(Args&&... args)
: erased_variant{ A<Args...>(std::forward<Args>(args)...) } { inject_adl_definition<Args...>(); }
template <class F>
void visit(F&& f) {
std::any_cast<variant_type<F, type_tag>&>(erased_variant).visit(std::forward<F>(f));
}
private:
std::any erased_variant;
};
int main() {
Wrapper wrapper(9, 8.9, std::string("hello"));
wrapper.visit([](auto&& t) {
std::println("{}", t);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment