repr 0.1
Reconstructable string representations and more
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
cpp.h
Go to the documentation of this file.
#pragma once
#include <cstddef>
#include <string>
#include <string_view>
#include <type_traits>
namespace librepr {
struct CppVisitor {
private:
template <typename T>
auto name(T const& info) {
return std::string{info.name()};
}
template <typename T>
auto name(T const&) {
return REPR_FORMAT("UNNAMED_{}", unnamed_count);
}
template <typename T>
void print_name(T const& info) {
if constexpr (std::is_const_v<typename T::type>){
result << " const";
}
result << ' ' << name(info);
}
[[nodiscard]] auto get_indent() const { return std::string(indent_amount * indent_level, ' '); }
void print_struct(category::has_members auto info, std::string_view name) {
result << get_indent() << "struct " << name << " {\n";
info.visit(*this);
result << get_indent() << '}';
}
public:
template <category::has_members T>
auto operator()(T info) {
auto full_name = info.type_name();
if constexpr (category::has_parent<T>) {
auto parent_name = T::parent::type_name();
if (name.starts_with(parent_name)) {
name.remove_prefix(parent_name.size() + 2);
print_struct(info, name);
} else {
// namespace mismatch -> defined out of line
if (auto pos = name.rfind("::"); pos != std::string_view::npos) {
namespace_ = name.substr(0, pos);
name = name.substr(pos + 2);
}
if (!namespace_.empty()) {
result << get_indent() << "namespace " << namespace_ << " { \n";
}
print_struct(info, name);
result << ";\n";
if (!namespace_.empty()) {
result << "}\n";
}
result << get_indent() << full_name; // output type name
}
} else {
print_struct(info, name);
}
if (indent_level != 0){
print_name(info);
}
result << ";\n";
}
template <typename T>
auto operator()(T info) {
result << get_indent() << "enum ";
if constexpr (is_scoped) {
result << "class ";
}
auto raw_name = info.type_name();
auto name = std::string_view{raw_name};
if constexpr (category::has_parent<T>){
auto parent_name = T::parent::type_name();
if (name.starts_with(parent_name)) {
name.remove_prefix(parent_name.size() + 2);
}
}
result << name << " {\n";
for (auto const& enumerator : info.enumerator_names) {
auto name = (is_scoped) ? enumerator : enumerator.substr(enumerator.rfind("::") + 2);
result << get_indent() << name << ",\n";
}
result << get_indent() << "}";
print_name(info);
result << ";\n";
}
template <typename T>
template <typename T>
auto operator()(T info) {
result << get_indent() << info.type_name();
print_name(info);
result << ";\n";
}
};
} // namespace librepr