forked from standardese/cppast
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcpp_entity_ref.hpp
More file actions
131 lines (113 loc) · 4.55 KB
/
Copy pathcpp_entity_ref.hpp
File metadata and controls
131 lines (113 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (C) 2017-2018 Jonathan Müller <[email protected]>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.
#ifndef CPPAST_CPP_ENTITY_REF_HPP_INCLUDED
#define CPPAST_CPP_ENTITY_REF_HPP_INCLUDED
#include <vector>
#include <type_safe/variant.hpp>
#include <cppast/detail/assert.hpp>
#include <cppast/cpp_entity_index.hpp>
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
{
public:
/// \effects Creates it giving it the target id and name.
basic_cpp_entity_ref(cpp_entity_id target_id, std::string target_name)
: target_(std::move(target_id)), name_(std::move(target_name))
{
}
/// \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 Whether or not it refers to multiple entities.
bool is_overloaded() const noexcept
{
return target_.has_value(type_safe::variant_type<std::vector<cpp_entity_id>>{});
}
/// \returns The number of entities it refers to.
type_safe::size_t no_overloaded() const noexcept
{
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);
}
}
/// \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
std::vector<type_safe::object_ref<const T>> get(const cpp_entity_index& idx) const
{
std::vector<type_safe::object_ref<const T>> result;
get_impl(std::is_convertible<cpp_namespace&, T&>{}, result, idx);
return result;
}
private:
void get_impl(std::true_type, std::vector<type_safe::object_ref<const T>>& result,
const cpp_entity_index& idx) const
{
for (auto& cur : id())
for (auto& ns : idx.lookup_namespace(cur))
result.push_back(ns);
if (!std::is_same<T, cpp_namespace>::value)
get_impl(std::false_type{}, result, idx);
}
void get_impl(std::false_type, std::vector<type_safe::object_ref<const T>>& result,
const cpp_entity_index& idx) const
{
for (auto& cur : id())
{
auto entity = idx.lookup(cur).map([](const cpp_entity& e) {
DEBUG_ASSERT(Predicate{}(e), detail::precondition_error_handler{},
"invalid entity type");
return type_safe::ref(static_cast<const T&>(e));
});
if (entity)
result.push_back(type_safe::ref(entity.value()));
}
}
type_safe::variant<cpp_entity_id, std::vector<cpp_entity_id>> target_;
std::string name_;
};
/// \exclude
namespace detail
{
struct cpp_entity_ref_predicate
{
bool operator()(const cpp_entity&)
{
return true;
}
};
}
/// A [cppast::basic_cpp_entity_ref]() to any [cppast::cpp_entity]().
using cpp_entity_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_entity_ref_predicate>;
} // namespace cppast
#endif // CPPAST_CPP_ENTITY_REF_HPP_INCLUDED