Skip to content

Instantly share code, notes, and snippets.

@yuyoyuppe
Last active November 16, 2022 22:50
Show Gist options
  • Save yuyoyuppe/a96b7ec1b27b0f6cd735869a436914f3 to your computer and use it in GitHub Desktop.
Save yuyoyuppe/a96b7ec1b27b0f6cd735869a436914f3 to your computer and use it in GitHub Desktop.
Recursive variant printer
#include <string>
#include <format>
#include <variant>
#include <cstdio>
#include <regex>
#include <vector>
template <typename T, template <typename...> class Of>
struct is_specialization : std::false_type
{
};
template <template <typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref> : std::true_type
{
};
template <typename T, template <typename...> class Of>
constexpr bool is_specialization_v = is_specialization<T, Of>::value;
template <class F>
struct y_combinator
{
F f;
template <class... Args>
decltype(auto) operator()(Args &&... args) const
{
return f(*this, std::forward<Args>(args)...);
}
};
template <class F>
y_combinator<std::decay_t<F>> fix(F && f)
{
return {std::forward<F>(f)};
}
int main()
{
std::vector<std::string> names;
const auto printer = fix([&](auto printer, auto & v) {
using v_t = std::decay_t<decltype(v)>;
names.emplace_back(typeid(v_t).name());
if constexpr(is_specialization_v<v_t, std::variant>)
std::visit(printer, v);
});
using v0 = std::variant<std::vector<std::string>, float, int>;
using v1 = std::variant<double, v0>;
using v2 = std::variant<v1, short>;
v0 var0 = 228;
v1 var1 = var0;
v2 var2 = var1;
printer(var2);
using rp = std::pair<std::regex, std::string>;
const std::vector repls = {rp{" std::", " "},
rp{"class ", ""},
rp{"struct ", ""},
rp{R"(,allocator<([^>]+)>)", ""},
rp{R"(basic_string<char,char_traits<char> )", "string"},
rp{R"(\s>(?=\s))", ""},
rp{R"(\s>)", ">"}};
for(const auto & [re, replace] : repls)
for(auto & name : names)
name = std::regex_replace(name, re, replace);
for(size_t i = 0; i < names.size() - 1; ++i)
{
const auto & next_lvl = names[i + 1];
names[i].replace(names[i].find(next_lvl), next_lvl.size(), "#" + std::to_string(i));
}
for(size_t i = 0; i < names.size(); ++i)
{
if(i > 0)
{
printf("%d.", (int)i - 1);
for(size_t l = 0; l < i * 2 - 1; ++l)
printf(" ");
}
printf("%s\n", names[i].c_str());
}
/*
variant<#0,short>
0. variant<double,#1>
1. variant<vector<string>>,float,#2>
2. int
*/
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment