-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: flavor refactor, reduce duplication (#3407)
Reduces duplication in Flavor classes by using a macro that combines pointer_view with struct fields (along with a new get_all getter that is perhaps more ergonomic) and subclassing. Note that this is a stepping stone, ideally #788 is used instead of multiple inheritance Also resolves #784 - Introduces a RefVector class, like `std::vector<T&>` (which is impossible). It is backed by a pointer, and gives operator[] and iterator semantics on the underlying derefenced pointer. Compare std::vector<std::reference_wrapper<T>>, which would operate more like actual pointers (you change the reference, not the value held by the reference). - Introduces a get_all alternative to pointer_view that uses RefVector, update other types to use RefVector, get rid of the HandleType in flavor entity classes - Removes some flavor base classes that didn't do much after array backing removal. Now we get rid of virtual base class methods here, but I don't think it makes sense to do polymorphism in two ways. We can instead use concepts if we want to constrain this with a static assert - Introduces macros that define flavor classes in flavor_macros.hpp. These remove duplication of pointer view and normal listing. - Use inheritance to remove duplication in the larger AllEntities classes in GoblinUltra and GoblinTranslator - Removes modernize-use-nodiscard - too noisy a linter setting, I doubt we'd hit a bug that it would fix (i.e. if you return error codes it can be useful to not ignore them). --------- Co-authored-by: ludamad <[email protected]>
- Loading branch information
Showing
30 changed files
with
2,126 additions
and
3,173 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#include "barretenberg/common/assert.hpp" | ||
#include <array> | ||
#include <cstddef> | ||
#include <initializer_list> | ||
#include <iterator> | ||
#include <stdexcept> | ||
|
||
// TODO(https://github.com/AztecProtocol/barretenberg/issues/794) namespace this once convenient | ||
/** | ||
* @brief A template class for a reference array. Behaves as if std::array<T&, N> was possible. | ||
* | ||
* This class provides a fixed-size array of pointers to elements of type T, exposed as references. | ||
* It offers random access to its elements and provides an iterator class | ||
* for traversal. | ||
* | ||
* @tparam T The type of elements stored in the array. | ||
* @tparam N The size of the array. | ||
*/ | ||
template <typename T, std::size_t N> class RefArray { | ||
public: | ||
RefArray(const std::array<T*, N>& ptr_array) | ||
{ | ||
std::size_t i = 0; | ||
for (T& elem : ptr_array) { | ||
storage[i++] = &elem; | ||
} | ||
} | ||
RefArray(std::initializer_list<T&> init) | ||
{ | ||
if (init.size() != N) { | ||
throw std::invalid_argument("Initializer list size does not match RefArray size"); | ||
} | ||
std::size_t i = 0; | ||
for (auto& elem : init) { | ||
storage[i++] = &elem; | ||
} | ||
} | ||
|
||
T& operator[](std::size_t idx) const | ||
{ | ||
ASSERT(idx < N); | ||
return *storage[idx]; | ||
} | ||
|
||
/** | ||
* @brief Nested iterator class for RefArray, based on indexing into the pointer array. | ||
* Provides semantics similar to what would be expected if std::array<T&, N> was possible. | ||
*/ | ||
class iterator { | ||
public: | ||
/** | ||
* @brief Constructs an iterator for a given RefArray object. | ||
* | ||
* @param array Pointer to the RefArray object. | ||
* @param pos The starting position in the array. | ||
*/ | ||
iterator(RefArray const* array, std::size_t pos) | ||
: array(array) | ||
, pos(pos) | ||
{} | ||
|
||
T& operator*() const { return (*array)[pos]; } | ||
|
||
iterator& operator++() | ||
{ | ||
pos++; | ||
return *this; | ||
} | ||
|
||
iterator operator++(int) | ||
{ | ||
iterator temp = *this; | ||
++(*this); | ||
return temp; | ||
} | ||
|
||
bool operator==(iterator const& other) const { return pos == other.pos; } | ||
bool operator!=(iterator const& other) const { return pos != other.pos; } | ||
|
||
private: | ||
RefArray const* array; | ||
std::size_t pos; | ||
}; | ||
|
||
/** | ||
* @brief Returns an iterator to the beginning of the RefArray. | ||
* | ||
* @return An iterator to the first element. | ||
*/ | ||
iterator begin() const { return iterator(this, 0); } | ||
/** | ||
* @brief Returns an iterator to the end of the RefArray. | ||
* | ||
* @return An iterator to the element following the last element. | ||
*/ | ||
iterator end() const { return iterator(this, N); } | ||
|
||
private: | ||
// We are making a high-level array, for simplicity having a C array as backing makes sense. | ||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) | ||
T* storage[N]; | ||
}; | ||
|
||
/** | ||
* @brief Deduction guide for the RefArray class. | ||
* Allows for RefArray {a, b, c} without explicit template params. | ||
*/ | ||
template <typename T, typename... Ts> RefArray(T&, Ts&...) -> RefArray<T, 1 + sizeof...(Ts)>; | ||
|
||
/** | ||
* @brief Concatenates multiple RefArray objects into a single RefArray. | ||
* | ||
* This function takes multiple RefArray objects as input and concatenates them into a single | ||
* RefArray. | ||
* @tparam T The type of elements in the RefArray. | ||
* @tparam Ns The sizes of the input RefArrays. | ||
* @param ref_arrays The RefArray objects to be concatenated. | ||
* @return RefArray object containing all elements from the input arrays. | ||
*/ | ||
template <typename T, std::size_t... Ns> RefArray<T, (Ns + ...)> concatenate(const RefArray<T, Ns>&... ref_arrays) | ||
{ | ||
// Fold expression to calculate the total size of the new array using fold expression | ||
constexpr std::size_t TotalSize = (Ns + ...); | ||
std::array<T*, TotalSize> concatenated; | ||
|
||
std::size_t offset = 0; | ||
// Copies elements from a given RefArray to the concatenated array | ||
auto copy_into = [&](const auto& ref_array, std::size_t& offset) { | ||
for (std::size_t i = 0; i < ref_array.size(); ++i) { | ||
concatenated[offset + i] = &ref_array[i]; | ||
} | ||
offset += ref_array.size(); | ||
}; | ||
|
||
// Fold expression to copy elements from each input RefArray to the concatenated array | ||
(..., copy_into(ref_arrays, offset)); | ||
|
||
return RefArray<T, TotalSize>{ concatenated }; | ||
} |
Oops, something went wrong.