: m_otag(open_tag)
, m_ctag(close_tag)
{
m_cdn.reserve(sizeof...(args));
const auto add = based::overload {
[&](const element_base& elem) { m_cdn.emplace_back(elem); },
[&](const std::ranges::forward_range auto& range)
[this](const std::ranges::forward_range auto& range)
requires(!std::constructible_from<std::string_view, decltype(range)>)
{
m_cdn.reserve(std::size(m_cdn) + std::size(range));
m_cdn.insert(std::end(m_cdn), std::begin(range), std::end(range));
},
[&](const std::string_view data)
{ m_cdn.emplace_back(std::string(data)); },
};
[this](const std::string_view data)
{
m_cdn.emplace_back(std::string(data));
},
[this](const element_base& elem)
{
m_cdn.emplace_back(elem);
},
};
m_cdn.reserve(sizeof...(args));
(add(std::forward<Args>(args)), ...);
}
void render_children(std::ostream& out, std::size_t indent_value) const
{
const std::string indent(indent_value, ' ');
const auto render = based::overload {
[&](const element_base& elem)
{
elem.render(out, indent_value);
},
[&](const std::string& data)
{
out << indent << data << '\n';
},
};
for (const auto& child : m_cdn) {
std::visit(render, child);
}
}
void render(std::ostream& out, std::size_t indent_value) const
{
const std::string indent(indent_value, ' ');
if (m_otag.empty()) {
render_children(out, indent_value);
return;
}
out << indent << m_otag << '\n';
render_children(out, indent_value + 2);
out << indent << m_ctag << '\n';
}
public:
explicit operator std::string() const
{