Last active
November 16, 2022 22:50
-
-
Save yuyoyuppe/a96b7ec1b27b0f6cd735869a436914f3 to your computer and use it in GitHub Desktop.
Recursive variant printer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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