Add support for overloaded entity references
This commit is contained in:
parent
cb9ad57e87
commit
08717b2ae7
8 changed files with 197 additions and 47 deletions
|
|
@ -101,8 +101,9 @@ namespace cppast
|
|||
|
||||
private:
|
||||
cpp_base_class(const cpp_type_ref& base, cpp_access_specifier_kind access, bool is_virtual)
|
||||
: cpp_entity(base.name()), base_id_(base.id()), access_(access), virtual_(is_virtual)
|
||||
: cpp_entity(base.name()), base_id_(base.id()[0u]), access_(access), virtual_(is_virtual)
|
||||
{
|
||||
DEBUG_ASSERT(!base.is_overloaded(), detail::precondition_error_handler{});
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@
|
|||
#ifndef CPPAST_CPP_ENTITY_REF_HPP_INCLUDED
|
||||
#define CPPAST_CPP_ENTITY_REF_HPP_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <type_safe/variant.hpp>
|
||||
|
||||
#include <cppast/cpp_entity_index.hpp>
|
||||
|
||||
namespace cppast
|
||||
|
|
@ -12,6 +16,10 @@ namespace cppast
|
|||
enum class cpp_entity_kind;
|
||||
|
||||
/// A basic reference to some kind of [cppast::cpp_entity]().
|
||||
///
|
||||
/// It can either refer to a single [cppast::cpp_entity]()
|
||||
/// or multiple.
|
||||
/// In the later case it is *overloaded*.
|
||||
template <typename T, typename Predicate>
|
||||
class basic_cpp_entity_ref
|
||||
{
|
||||
|
|
@ -22,32 +30,152 @@ namespace cppast
|
|||
{
|
||||
}
|
||||
|
||||
/// \effects Creates it giving it multiple target ids and name.
|
||||
/// \notes This is to refer to an overloaded function.
|
||||
basic_cpp_entity_ref(std::vector<cpp_entity_id> target_ids, std::string target_name)
|
||||
: target_(std::move(target_ids)), name_(std::move(target_name))
|
||||
{
|
||||
}
|
||||
|
||||
/// \returns The name of the reference, as spelled in the source code.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_entity_id]() of the entity it refers to.
|
||||
const cpp_entity_id& id() const noexcept
|
||||
/// \returns Whether or not it refers to multiple entities.
|
||||
bool is_overloaded() const noexcept
|
||||
{
|
||||
return target_;
|
||||
return target_.has_value(type_safe::variant_type<std::vector<cpp_entity_id>>{});
|
||||
}
|
||||
|
||||
/// \returns An optional reference to the [cppast::cpp_entity]() it refers to.
|
||||
type_safe::optional_ref<const T> get(const cpp_entity_index& idx) const noexcept
|
||||
/// \returns The number of entities it refers to.
|
||||
type_safe::size_t no_overloaded() const noexcept
|
||||
{
|
||||
auto entity = idx.lookup(target_);
|
||||
if (!entity)
|
||||
return type_safe::nullopt;
|
||||
DEBUG_ASSERT(Predicate{}(entity.value()), detail::precondition_error_handler{},
|
||||
"predicate not fulfilled");
|
||||
return static_cast<const T&>(entity.value());
|
||||
return id().size();
|
||||
}
|
||||
|
||||
/// \returns An array reference to the id or ids it refers to.
|
||||
type_safe::array_ref<const cpp_entity_id> id() const noexcept
|
||||
{
|
||||
if (is_overloaded())
|
||||
{
|
||||
auto& vec = target_.value(type_safe::variant_type<std::vector<cpp_entity_id>>{});
|
||||
return type_safe::ref(vec.data(), vec.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& id = target_.value(type_safe::variant_type<cpp_entity_id>{});
|
||||
return type_safe::ref(&id, 1u);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_entity_id target_;
|
||||
std::string name_;
|
||||
class ref_impl
|
||||
{
|
||||
public:
|
||||
ref_impl(type_safe::object_ref<const cpp_entity_index> idx,
|
||||
type_safe::array_ref<const cpp_entity_id> ids)
|
||||
: ids_(ids), index_(idx)
|
||||
{
|
||||
}
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
using value_type = type_safe::optional_ref<const T>;
|
||||
using reference = value_type;
|
||||
using pointer = value_type*;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
reference operator*() const noexcept
|
||||
{
|
||||
return (*ref_)[i_];
|
||||
}
|
||||
|
||||
pointer operator->() const noexcept
|
||||
{
|
||||
return &(*ref_)[i_];
|
||||
}
|
||||
|
||||
iterator& operator++() noexcept
|
||||
{
|
||||
++i_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int)noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const iterator& a, const iterator& b) noexcept
|
||||
{
|
||||
return a.ref_ == b.ref_ && a.i_ == b.i_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const iterator& a, const iterator& b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
private:
|
||||
iterator(type_safe::object_ref<const ref_impl> ref, type_safe::index_t i)
|
||||
: ref_(ref), i_(i)
|
||||
{
|
||||
}
|
||||
|
||||
type_safe::object_ref<const ref_impl> ref_;
|
||||
type_safe::index_t i_;
|
||||
|
||||
friend ref_impl;
|
||||
};
|
||||
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
return iterator(type_safe::ref(*this), 0u);
|
||||
}
|
||||
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return iterator(type_safe::ref(*this), size());
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const T> operator[](type_safe::index_t i) const
|
||||
{
|
||||
return index_->lookup(ids_[i]).map([](const cpp_entity& e) -> const T& {
|
||||
DEBUG_ASSERT(Predicate{}(e), detail::precondition_error_handler{},
|
||||
"predicate not fulfilled");
|
||||
return static_cast<const T&>(e);
|
||||
});
|
||||
}
|
||||
|
||||
type_safe::size_t size() const noexcept
|
||||
{
|
||||
return ids_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::array_ref<const cpp_entity_id> ids_;
|
||||
type_safe::object_ref<const cpp_entity_index> index_;
|
||||
};
|
||||
|
||||
public:
|
||||
/// \returns An array reference to the entities it refers to.
|
||||
/// The return type provides `operator[]` + `size()`,
|
||||
/// as well as `begin()` and `end()` returning forward iterators.
|
||||
/// \exclude return
|
||||
ref_impl get(const cpp_entity_index& idx) const noexcept
|
||||
{
|
||||
return ref_impl(type_safe::ref(idx), id());
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::variant<cpp_entity_id, std::vector<cpp_entity_id>> target_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
|
|
|
|||
|
|
@ -101,8 +101,9 @@ namespace cppast
|
|||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_include_directive(const cpp_file_ref& target, cpp_include_kind kind)
|
||||
: cpp_entity(target.name()), target_(target.id()), kind_(kind)
|
||||
: cpp_entity(target.name()), target_(target.id()[0u]), kind_(kind)
|
||||
{
|
||||
DEBUG_ASSERT(!target.is_overloaded(), detail::precondition_error_handler{});
|
||||
}
|
||||
|
||||
cpp_entity_id target_;
|
||||
|
|
|
|||
|
|
@ -183,10 +183,10 @@ namespace cppast
|
|||
/// \effects Sets the entity that is being templated and the primary template.
|
||||
cpp_template_specialization(std::unique_ptr<cpp_entity> entity,
|
||||
const cpp_template_ref& templ)
|
||||
: cpp_template(std::move(entity)), templ_(templ.id())
|
||||
: cpp_template(std::move(entity)), templ_(templ.id()[0u])
|
||||
{
|
||||
DEBUG_ASSERT(templ.name() == entity->name(), detail::precondition_error_handler{},
|
||||
"invalid name of template ref");
|
||||
DEBUG_ASSERT(!templ.is_overloaded() && templ.name() == entity->name(),
|
||||
detail::precondition_error_handler{}, "invalid name of template ref");
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue