Utilities#
pw_containers: Generic collections of objects for embedded devices
In addition to containers, this module includes some types and functions for working with containers and the data within them.
pw::containers::FilteredView#
-
template<typename Container, typename Filter>
class FilteredView# pw::containers::FilteredView
provides a view of a container with only elements that match the specified filter. This class is similar to C++20’s std::ranges::filter_view.FilteredView
works with any container with an incrementable iterator. Theback()
function currently requires a bidirectional iterator.To create a
FilteredView
, pass a container and a filter predicate, which may be any callable type including a function pointer, lambda, orpw::Function
.std::array<int, 99> kNumbers = {3, 1, 4, 1, ...}; for (int n : FilteredView(kNumbers, [](int v) { return v % 2 == 0; })) { PW_LOG_INFO("This number is even: %d", n); }
pw::containers::WrappedIterator#
pw::containers::WrappedIterator
is a class that makes it easy to wrap an
existing iterator type. It reduces boilerplate by providing operator++
,
operator--
, operator==
, operator!=
, and the standard iterator
aliases (difference_type
, value_type
, etc.). It does not provide the
dereference operator; that must be supplied by a derived class.
Example#
To use it, create a class that derives from WrappedIterator
and define
operator*()
and operator->()
as appropriate. The new iterator might
apply a transformation to or access a member of the values provided by the
original iterator. The following example defines an iterator that multiplies the
values in an array by 2.
1using pw::containers::WrappedIterator;
2
3// Multiplies values in a std::array by two.
4class DoubleIterator : public WrappedIterator<DoubleIterator, const int*, int> {
5 public:
6 constexpr DoubleIterator(const int* it) : WrappedIterator(it) {}
7 int operator*() const { return value() * 2; }
8};
9
10// Returns twice the sum of the elements in a array of integers.
11template <size_t kArraySize>
12int DoubleSum(const std::array<int, kArraySize>& c) {
13 int sum = 0;
14 for (DoubleIterator it(c.data()); it != DoubleIterator(c.data() + c.size());
15 ++it) {
16 // The iterator yields doubles instead of the original values.
17 sum += *it;
18 }
19 return sum;
20}
Basic functional programming#
WrappedIterator
may be used in concert with FilteredView
to create a
view that iterates over a matching values in a container and applies a
transformation to the values. For example, it could be used with
FilteredView
to filter a list of packets and yield only one field from the
packet.
The combination of FilteredView
and WrappedIterator
provides some basic
functional programming features similar to (though much more cumbersome than)
generator expressions (or filter/map) in Python or streams
in Java 8. WrappedIterator
and FilteredView
require no memory
allocation, which is helpful when memory is too constrained to process the items
into a new container.
pw::containers::to_array#
pw::containers::to_array
is a C++14-compatible implementation of C++20’s
std::to_array.
In C++20, it is an alias for std::to_array
. It converts a C array to a
std::array
.
pw_containers/algorithm.h#
This header file provides container-based versions of algorithmic functions within the C++ standard library, based on pw_containers. The following standard library sets of functions are covered within this file:
<algorithm> functions
The standard library functions operate on iterator ranges; the functions within this API operate on containers, though many return iterator ranges.
All functions within this API are CamelCase instead of their std:: snake_case counterparts. Calls such as pw::containers::Foo(container, ...)
are equivalent to std::
functions such as std::foo(std::begin(cont), std::end(cont), ...)
. Functions that act on iterators but not conceptually on iterator ranges (e.g. std::iter_swap
)
-
template<typename C, typename Pred>
bool pw::containers::AllOf(const C &c, Pred &&pred)# Container-based version of the <algorithm>
std::all_of()
function to test if all elements within a container satisfy a condition.
-
template<typename C, typename Pred>
bool pw::containers::AnyOf(const C &c, Pred &&pred)# Container-based version of the <algorithm>
std::any_of()
function to test if any element in a container fulfills a condition.
-
template<typename C, typename Pred>
bool pw::containers::NoneOf(const C &c, Pred &&pred)# Container-based version of the <algorithm>
std::none_of()
function to test if no elements in a container fulfill a condition.
-
template<typename C, typename Function>
std::decay_t<Function> pw::containers::ForEach(C &&c, Function &&f)# Container-based version of the <algorithm>
std::for_each()
function to apply a function to a container’s elements.
-
template<typename C, typename T>
internal_algorithm::ContainerIter<C> pw::containers::Find(C &c, T &&value)# Container-based version of the <algorithm>
std::find()
function to find the first element containing the passed value within a container value.
-
template<typename C, typename Pred>
internal_algorithm::ContainerIter<C> pw::containers::FindIf(C &c, Pred &&pred)# Container-based version of the <algorithm>
std::find_if()
function to find the first element in a container matching the given condition.
-
template<typename C, typename Pred>
internal_algorithm::ContainerIter<C> pw::containers::FindIfNot(C &c, Pred &&pred)# Container-based version of the <algorithm>
std::find_if_not()
function to find the first element in a container not matching the given condition.
-
template<typename Sequence1, typename Sequence2>
internal_algorithm::ContainerIter<Sequence1> pw::containers::FindEnd(
)# Container-based version of the <algorithm>
std::find_end()
function to find the last subsequence within a container.
-
template<typename Sequence1, typename Sequence2, typename BinaryPredicate>
internal_algorithm::ContainerIter<Sequence1> pw::containers::FindEnd( - Sequence1 &sequence,
- Sequence2 &subsequence,
- BinaryPredicate &&pred,
Overload of
FindEnd()
for using a predicate evaluation other than==
as the function’s test condition.
-
template<typename C1, typename C2>
internal_algorithm::ContainerIter<C1> pw::containers::FindFirstOf(
)# Container-based version of the <algorithm>
std::find_first_of()
function to find the first element within the container that is also within the options container.
-
template<typename C1, typename C2, typename BinaryPredicate>
internal_algorithm::ContainerIter<C1> pw::containers::FindFirstOf( - C1 &container,
- C2 &options,
- BinaryPredicate &&pred,
Overload of
FindFirstOf()
for using a predicate evaluation other than==
as the function’s test condition.
-
template<typename Sequence>
internal_algorithm::ContainerIter<Sequence> pw::containers::AdjacentFind(Sequence &sequence)# Container-based version of the <algorithm>
std::adjacent_find()
function to find equal adjacent elements within a container.
-
template<typename Sequence, typename BinaryPredicate>
internal_algorithm::ContainerIter<Sequence> pw::containers::AdjacentFind( - Sequence &sequence,
- BinaryPredicate &&pred,
Overload of
AdjacentFind()
for using a predicate evaluation other than==
as the function’s test condition.
-
template<typename C, typename T>
internal_algorithm::ContainerDifferenceType<const C> pw::containers::Count(
)# Container-based version of the <algorithm>
std::count()
function to count values that match within a container.
-
template<typename C, typename Pred>
internal_algorithm::ContainerDifferenceType<const C> pw::containers::CountIf(
)# Container-based version of the <algorithm>
std::count_if()
function to count values matching a condition within a container.
-
template<typename C1, typename C2>
internal_algorithm::ContainerIterPairType<C1, C2> pw::containers::Mismatch(C1 &c1, C2 &c2)# Container-based version of the <algorithm>
std::mismatch()
function to return the first element where two ordered containers differ. Applies==
to the first N elements ofc1
andc2
, where N = min(size(c1), size(c2)).
-
template<typename C1, typename C2, typename BinaryPredicate>
internal_algorithm::ContainerIterPairType<C1, C2> pw::containers::Mismatch( - C1 &c1,
- C2 &c2,
- BinaryPredicate pred,
Overload of
Mismatch()
for using a predicate evaluation other than==
as the function’s test condition. Appliespred
to the first N elements ofc1
andc2
, where N = min(size(c1), size(c2)).
-
template<typename C1, typename C2>
bool pw::containers::Equal(const C1 &c1, const C2 &c2)# Container-based version of the <algorithm>
std::equal()
function to test whether two containers are equal.vector v1 = <1, 2, 3>; vector v2 = <1, 2, 3, 4>; EXPECT_TRUE(equal(std::begin(v1), std::end(v1), std::begin(v2))); EXPECT_FALSE(Equal(v1, v2));
Note
The semantics of
Equal()
are slightly different than those ofstd::equal()
. While the latter iterates over the second container only up to the size of the first container,Equal()
also checks whether the container sizes are equal. This better matches expectations aboutEqual()
based on its signature.
-
template<typename C1, typename C2, typename BinaryPredicate>
bool pw::containers::Equal( - const C1 &c1,
- const C2 &c2,
- BinaryPredicate &&pred,
Overload of
Equal()
for using a predicate evaluation other than==
as the function’s test condition.
-
template<typename C1, typename C2>
bool pw::containers::IsPermutation(const C1 &c1, const C2 &c2)# Container-based version of the <algorithm>
std::is_permutation()
function to test whether a container is a permutation of another.`
-
template<typename C1, typename C2, typename BinaryPredicate>
bool pw::containers::IsPermutation( - const C1 &c1,
- const C2 &c2,
- BinaryPredicate &&pred,
Overload of
IsPermutation()
for using a predicate evaluation other than==
as the function’s test condition.
-
template<typename Sequence1, typename Sequence2>
internal_algorithm::ContainerIter<Sequence1> pw::containers::Search(
)# Container-based version of the <algorithm>
std::search()
function to search a container for a subsequence.
-
template<typename Sequence1, typename Sequence2, typename BinaryPredicate>
internal_algorithm::ContainerIter<Sequence1> pw::containers::Search( - Sequence1 &sequence,
- Sequence2 &subsequence,
- BinaryPredicate &&pred,
Overload of
Search()
for using a predicate evaluation other than==
as the function’s test condition.
-
template<typename Sequence, typename Size, typename T>
internal_algorithm::ContainerIter<Sequence> pw::containers::SearchN(
)# Container-based version of the <algorithm>
std::search_n()
function to search a container for the first sequence of N elements.
-
template<typename Sequence, typename Size, typename T, typename BinaryPredicate>
internal_algorithm::ContainerIter<Sequence> pw::containers::SearchN( - Sequence &sequence,
- Size count,
- T &&value,
- BinaryPredicate &&pred,
Overload of
SearchN()
for using a predicate evaluation other than==
as the function’s test condition.