NEURON
view_utils.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <cstddef> // std::size_t
3 #include <utility> // std::as_const, std::move
4 
5 namespace neuron::container {
6 /**
7  * @brief Base class for neuron::container::soa<...> handles.
8  * @tparam Identifier Identifier type used for this handle. This encodes both
9  * the referred-to type (Node, Mechanism, ...) and the
10  * ownership semantics (owning, non-owning). The instance of
11  * this type manages both the pointer-to-row and
12  * pointer-to-storage members of the handle.
13  *
14  * This provides some common methods that are neither specific to a particular data
15  * structure (Node, Mechanism, ...) nor specific to whether or not the handle
16  * has owning semantics or not. Methods that are specific to the data type (e.g.
17  * Node) belong in the interface template for that type (e.g. Node::interface).
18  * Methods that are specific to the owning/non-owning semantics belong in the
19  * generic templates non_owning_identifier<T> and owning_identifier<T>.
20  *
21  * The typical way these components fit together is:
22  *
23  * Node::identifier = non_owning_identifier<Node::storage>
24  * Node::owning_identifier = owning_identifier<Node::storage>
25  * Node::handle = Node::interface<Node::identifier>
26  * inherits from: handle_base<Node::identifier>
27  * Node::owning_handle = Node::interface<Node::owning_identifier>
28  * inherits from handle_base<Node::owning_identifier>
29  *
30  * Where the "identifier" types should be viewed as an implementation detail and
31  * the handle types as user-facing.
32  */
33 template <typename Identifier>
34 struct handle_base {
35  /**
36  * @brief Construct a handle from an identifier.
37  */
38  handle_base(Identifier identifier)
39  : m_identifier{std::move(identifier)} {}
40 
41  /**
42  * @brief Return current offset in the underlying storage where this object lives.
43  */
44  [[nodiscard]] std::size_t current_row() const {
45  return m_identifier.current_row();
46  }
47 
48  /**
49  * @brief Obtain a lightweight identifier of the current entry.
50  *
51  * The return type is essentially std::size_t* -- it does not contain a
52  * pointer/reference to the actual storage container.
53  */
55  return m_identifier;
56  }
57 
58  /**
59  * @brief This is a workaround for id sometimes being a macro.
60  * @todo Remove those macros once and for all.
61  */
62  [[nodiscard]] auto id_hack() const {
63  return id();
64  }
65 
66  /**
67  * @brief Obtain a reference to the storage this handle refers to.
68  */
70  return m_identifier.underlying_storage();
71  }
72 
73  /**
74  * @brief Obtain a const reference to the storage this handle refers to.
75  */
76  auto const& underlying_storage() const {
77  return m_identifier.underlying_storage();
78  }
79 
80  protected:
81  /**
82  * @brief Get a data_handle<T> referring to the given field inside this handle.
83  * @tparam Tag Tag type of the field we want a data_handle to.
84  *
85  * This is used to implement methods like area_handle() and v_handle() in
86  * the interface templates.
87  *
88  * @todo const cleanup -- should there be a const version returning
89  * data_handle<T const>?
90  */
91  template <typename Tag>
92  [[nodiscard]] auto get_handle() {
93  return underlying_storage().template get_handle<Tag>(this->id());
94  }
95 
96  /**
97  * @brief Get a data_handle<T> referring to the (runtime) field_index-th
98  * copy of a given (static) field.
99  * @tparam Tag Tag type of the set of fields the from which the
100  * field_index-th one is being requested.
101 
102  * @todo Const cleanup as above for the zero-argument version.
103  */
104  template <typename Tag>
105  [[nodiscard]] auto get_handle(int field_index, int array_offset = 0) {
106  return underlying_storage().template get_field_instance_handle<Tag>(this->id(),
107  field_index,
108  array_offset);
109  }
110  template <typename Tag>
111  [[nodiscard]] auto& get() {
112  return underlying_storage().template get<Tag>(current_row());
113  }
114  template <typename Tag>
115  [[nodiscard]] auto const& get() const {
116  return underlying_storage().template get<Tag>(current_row());
117  }
118  /**
119  * @brief Get the instance of the given tag type from underlying storage.
120  * @tparam Tag The tag type.
121  * @return Const reference to the given tag type instance inside the ~global storage struct.
122  *
123  * This is a thin wrapper that calls @c soa::get_tag<Tag> on the storage container (currently an
124  * instance of @c Node::storage or @c Mechanism::storage) that this handle refers to an instance
125  * inside.
126  */
127  template <typename Tag>
128  [[nodiscard]] constexpr Tag const& get_tag() const {
129  return underlying_storage().template get_tag<Tag>();
130  }
131  template <typename Tag>
132  [[nodiscard]] auto& get(int field_index, int array_offset = 0) {
133  return underlying_storage().template get_field_instance<Tag>(current_row(),
134  field_index,
135  array_offset);
136  }
137  template <typename Tag>
138  [[nodiscard]] auto const& get(int field_index, int array_offset = 0) const {
139  return underlying_storage().template get_field_instance<Tag>(current_row(),
140  field_index,
141  array_offset);
142  }
143 
144  private:
145  Identifier m_identifier;
146 };
147 } // namespace neuron::container
void move(Item *q1, Item *q2, Item *q3)
Definition: list.cpp:200
Struct used to index SoAoS data, such as array range variables.
Base class for neuron::container::soa<...> handles.
Definition: view_utils.hpp:34
auto get_handle()
Get a data_handle<T> referring to the given field inside this handle.
Definition: view_utils.hpp:92
std::size_t current_row() const
Return current offset in the underlying storage where this object lives.
Definition: view_utils.hpp:44
auto & underlying_storage()
Obtain a reference to the storage this handle refers to.
Definition: view_utils.hpp:69
auto id_hack() const
This is a workaround for id sometimes being a macro.
Definition: view_utils.hpp:62
auto const & underlying_storage() const
Obtain a const reference to the storage this handle refers to.
Definition: view_utils.hpp:76
auto & get(int field_index, int array_offset=0)
Definition: view_utils.hpp:132
auto get_handle(int field_index, int array_offset=0)
Get a data_handle<T> referring to the (runtime) field_index-th copy of a given (static) field.
Definition: view_utils.hpp:105
non_owning_identifier_without_container id() const
Obtain a lightweight identifier of the current entry.
Definition: view_utils.hpp:54
handle_base(Identifier identifier)
Construct a handle from an identifier.
Definition: view_utils.hpp:38
auto const & get() const
Definition: view_utils.hpp:115
constexpr Tag const & get_tag() const
Get the instance of the given tag type from underlying storage.
Definition: view_utils.hpp:128
auto const & get(int field_index, int array_offset=0) const
Definition: view_utils.hpp:138
A non-owning permutation-stable identifier for an entry in a container.