From f6b1806f47ee1f637c56ddd9a33fb40205a6d8f8 Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 24 Sep 2023 16:19:38 +0200 Subject: [PATCH 01/11] first commit for map --- include/map.h | 724 ++++++++++++++++++++++++++++++++++++++++++++++ include/set.h | 8 +- tests/map_test.cc | 36 +++ 3 files changed, 764 insertions(+), 4 deletions(-) create mode 100644 include/map.h create mode 100644 tests/map_test.cc diff --git a/include/map.h b/include/map.h new file mode 100644 index 0000000..c798c9e --- /dev/null +++ b/include/map.h @@ -0,0 +1,724 @@ +// MIT License +// +// Copyright (c) 2023 Ioannis Kaliakatsos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once +#include +#include +#include "optional.h" + +namespace fcpp { + +template +class vector; + +// A lightweight wrapper around std::map, enabling fluent and functional +// programming on the map itself, rather than using the more procedural style +// of the standard library algorithms. +template > +class map +{ +public: + map() + : m_map() + { + } + + explicit map(std::set set) + : m_map(std::move(set)) + { + } + +// explicit map(const std::vector& vector) +// : m_map(vector.begin(), vector.end()) +// { +// } +// +// explicit map(const vector& vector) +// : m_map(vector.begin(), vector.end()) +// { +// } +// +// explicit set(const std::initializer_list& list) +// : m_map(list.begin(), list.end()) +// { +// } + +// // Returns the set of elements which belong to the current set but not in the other set. +// // In Venn diagram notation, if A is the current set and B is the other set, then +// // the difference is the operation A – B = {x : x ∈ A and x ∉ B} +// // +// // example: +// // const fcpp::set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// // const fcpp::set set2(std::set({2, 5, 7, 10, 15, 17})); +// // const auto& diff = set1.difference(set2); +// // +// // outcome: +// // diff -> fcpp::set({1, 3, 8}) +// [[nodiscard]] set difference_with(const set& other) const { +// std::set diff; +// std::set_difference(begin(), +// end(), +// other.begin(), +// other.end(), +// std::inserter(diff, diff.begin())); +// return set(diff); +// } +// +// [[nodiscard]] set difference_with(const std::set& other) const { +// return difference_with(set(other)); +// } +// +// // Returns the set of elements which belong either to the current or the other set. +// // In Venn diagram notation, if A is the current set and B is the other set, then +// // the union is the operation A ∪ B = {x : x ∈ A or x ∈ B} +// // +// // example: +// // const fcpp::set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// // const fcpp::set set2(std::set({2, 5, 7, 10, 15, 17})); +// // const auto& combined = set1.set_union(set2); +// // +// // outcome: +// // combined -> fcpp::set({1, 2, 3, 5, 7, 8, 10, 15, 17}) +// [[nodiscard]] set union_with(const set& other) const { +// std::set combined; +// std::set_union(begin(), +// end(), +// other.begin(), +// other.end(), +// std::inserter(combined, combined.begin())); +// return set(combined); +// } +// +// [[nodiscard]] set union_with(const std::set& other) const { +// return union_with(set(other)); +// } +// +// // Returns the set of elements which belong to both the current and the other set. +// // In Venn diagram notation, if A is the current set and B is the other set, then +// // the intersection is the operation A ∩ B = {x : x ∈ A and x ∈ B} +// // +// // example: +// // const fcpp::set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// // const fcpp::set set2(std::set({2, 5, 7, 10, 15, 17})); +// // const auto& combined = set1.set_union(set2); +// // +// // outcome: +// // combined -> fcpp::set({2, 5, 7, 10}) +// [[nodiscard]] set intersect_with(const set& other) const { +// std::set intersection; +// std::set_intersection(begin(), +// end(), +// other.begin(), +// other.end(), +// std::inserter(intersection, intersection.begin())); +// return set(intersection); +// } +// +// [[nodiscard]] set intersect_with(const std::set& other) const { +// return intersect_with(set(other)); +// } +// +// // Returns the minimum key in the set, if it's not empty. +// // +// // example: +// // const fcpp::set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); +// // auto minimum = numbers.min(); +// // +// // // an empty's set minimum value +// // fcpp::set().min().has_value() // false +// // +// // outcome: +// // minimum.has_value() -> true +// // minimum.value() -> 1 +// [[nodiscard]] fcpp::optional_t min() const { +// const auto& it = std::min_element(begin(), end()); +// if (it != end()) { +// return *it; +// } +// return fcpp::optional_t(); +// } +// +// // Returns the maximum key in the set, if it's not empty. +// // +// // example: +// // const fcpp::set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); +// // auto maximum = numbers.max(); +// // +// // // an empty's set maximum value +// // fcpp::set().max().has_value() // false +// // +// // outcome: +// // maximum.has_value() -> true +// // maximum.value() -> 8 +// [[nodiscard]] fcpp::optional_t max() const { +// const auto& it = std::max_element(begin(), end()); +// if (it != end()) { +// return *it; +// } +// return fcpp::optional_t(); +// } +// +// // Performs the functional `map` algorithm, in which every element of the resulting set is the +// // output of applying the transform function on every element of this instance. +// // +// // example: +// // const fcpp::vector input_set({ 1, 3, -5 }); +// // const auto output_set = input_set.map([](const int& element) { +// // return std::to_string(element); +// // }); +// // +// // outcome: +// // output_set -> fcpp::set({ "-5", "1", "3" }) +// // +// // is equivalent to: +// // const fcpp::set input_set({ 1, 3, -5 }); +// // fcpp::set output_set; +// // for (auto const& key: input_set) { +// // output_set.insert(std::to_string(key)); +// // } +//#ifdef CPP17_AVAILABLE +// template , typename Transform, typename = std::enable_if_t>> +//#else +// template , typename Transform> +//#endif +// set map(Transform && transform) const +// { +// std::set transformed_set; +// for (const auto& key: m_map) { +// transformed_set.insert(transform(key)); +// } +// return set(transformed_set); +// } +// +// // Returns true if all keys match the predicate (return true) +// // +// // example: +// // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); +// // +// // // returns true +// // numbers.all_of([](const int &number) { +// // return number < 10; +// // }); +// // +// // // returns false +// // numbers.all_of([](const int &number) { +// // return number > 2; +// // }); +//#ifdef CPP17_AVAILABLE +// template >> +//#else +// template +//#endif +// bool all_of(Callable && unary_predicate) const +// { +// return std::all_of(begin(), +// end(), +// std::forward(unary_predicate)); +// } +// +// // Returns true if at least one key match the predicate (returns true) +// // +// // example: +// // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); +// // +// // // returns true +// // numbers.any_of([](const int &number) { +// // return number < 5; +// // }); +// // +// // // returns false +// // numbers.any_of([](const int &number) { +// // return number > 10; +// // }); +//#ifdef CPP17_AVAILABLE +// template >> +//#else +// template +//#endif +// bool any_of(Callable && unary_predicate) const +// { +// return std::any_of(begin(), +// end(), +// std::forward(unary_predicate)); +// } +// +// // Returns true if none of the keys match the predicate (all return false) +// // +// // example: +// // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); +// // +// // // returns true +// // numbers.none_of([](const int &number) { +// // return number > 10; +// // }); +// // +// // // returns false +// // numbers.none_of([](const int &number) { +// // return number < 6; +// // }); +//#ifdef CPP17_AVAILABLE +// template >> +//#else +// template +//#endif +// bool none_of(Callable && unary_predicate) const +// { +// return std::none_of(begin(), +// end(), +// std::forward(unary_predicate)); +// } +// +// // Performs the functional `reduce` (fold/accumulate) algorithm, by returning the result of +// // accumulating all the values in the vector to an initial value. (non-mutating) +// // +// // example: +// // const fcpp::set tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" }); +// // const auto sentence = tokens.reduce("", [](const std::string& partial, const std::string& token) { +// // return partial.length() != 0 +// // ? partial + " " + token +// // : token; +// // }); +// // +// // outcome: (a set does not allow multiple entries, and its elements are internally managed, order can vary) +// // +// // sentence -> std::string("brown dog fox jumps lazy over quick the"); +//#ifdef CPP17_AVAILABLE +// template >> +//#else +// template +//#endif +// U reduce(const U& initial, Reduce&& reduction) const +// { +// auto result = initial; +// for (const auto& x : m_map) +// { +// result = reduction(result, x); +// } +// return result; +// } +// +// // Performs the functional `filter` algorithm, in which all keys of this instance +// // which match the given predicate are kept (mutating) +// // +// // example: +// // fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); +// // numbers.filter([](const int& element) { +// // return element >= 1.5; +// // }); +// // +// // outcome: +// // numbers -> fcpp::set({ 2, 3, 9 }); +// // +// // is equivalent to: +// // fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); +// // for (auto i = 0; i < numbers.size(); ++i) { +// // if (numbers[i] >= 1.5) { +// // continue; +// // } +// // numbers.remove(i); +// // i--; +// // } +//#ifdef CPP17_AVAILABLE +// template >> +//#else +// template +//#endif +// set& filter(Filter && predicate_to_keep) +// { +// std::set copy; +// auto it = begin(); +// for (; it != end(); it++) { +// if (predicate_to_keep(*it)) { +// copy.insert(*it); +// } +// } +// m_map = std::move(copy); +// return *this; +// } +// +// // Performs the functional `filter` algorithm in a copy of this instance, in which all keys +// // of the copy which match the given predicate are kept (non-mutating) +// // +// // example: +// // const fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); +// // auto filtered_numbers = numbers.filtered([](const int& element) { +// // return element >= 1.5; +// // }); +// // +// // outcome: +// // filtered_numbers -> fcpp::set({ 2, 3, 9 }); +// // numbers -> fcpp::set({ 1, 3, -5, 2, -1, 9, -4 }); +//#ifdef CPP17_AVAILABLE +// template >> +//#else +// template +//#endif +// set filtered(Filter && predicate_to_keep) const +// { +// std::set copy; +// auto it = begin(); +// for (; it != end(); it++) { +// if (predicate_to_keep(*it)) { +// copy.insert(*it); +// } +// } +// return set(copy); +// } +// +//#ifdef CPP17_AVAILABLE +// template +// using deref_type = typename std::iterator_traits::value_type; +// +// template +// struct is_valid_iterator { +// static bool const value = std::is_constructible_v>; +// }; +//#endif +// +// // Performs the functional `zip` algorithm, in which every key of the resulting set is a +// // tuple of this instance's key (first) and the second set's key (second). +// // The sizes of the two sets must be equal. +// // +// // example: +// // const fcpp::set ages({ 25, 45, 30, 63 }); +// // const fcpp::set persons({ "Jake", "Bob", "Michael", "Philipp" }); +// // const auto zipped = ages.zip(persons); +// // +// // outcome: +// // zipped -> fcpp::set>({ +// // std::pair(25, "Bob"), +// // std::pair(30, "Jake"), +// // std::pair(45, "Michael"), +// // std::pair(63, "Philipp"), +// // }) +// template +// [[nodiscard]] set> zip(const set& set) const +// { +//#ifdef CPP17_AVAILABLE +// return zip_impl(set.begin(), set.end()); +//#else +// return zip_impl(set.begin(), set.end()); +//#endif +// } +// +// // Performs the functional `zip` algorithm. +// // The number of keys must match the set's size. +// // For more details, see the zip function which accepts a fcpp::set as input. +// template +// [[nodiscard]] set> zip(const std::set& set) const +// { +// return zip(fcpp::set(set)); +// } +// +// // Performs the functional `zip` algorithm by using the unique values of the vector. +// // The number of uniques vector values must match the set's size. +// // For more details, see the zip function which accepts a fcpp::set as input. +// template +// [[nodiscard]] set> zip(const vector& vector) const +// { +// const auto distinct_values = vector.distinct(); +// return zip(distinct_values); +// } +// +// // Performs the functional `zip` algorithm by using the unique values of the vector. +// // The number of uniques vector values must match the set's size. +// // For more details, see the zip function which accepts a fcpp::set as input. +// template +// [[nodiscard]] set> zip(const std::vector& vector) const +// { +// return zip(fcpp::vector(vector)); +// } +// +// // Executes the given operation for each key of the set. +// // The operation must not change the set's contents during execution. +//#ifdef CPP17_AVAILABLE +// template >> +//#else +// template +//#endif +// const set& for_each(Callable && operation) const +// { +// std::for_each(begin(), +// end(), +// std::forward(operation)); +// return *this; +// } +// +// vector keys() const { +// vector vec; +// vec.reserve(size()); +// for_each([&vec](const TKey& key) { +// vec.insert_back(key); +// }); +// return std::move(vec); +// } +// +// // Removes an element from the set, if it exists, potentially changing the set's contents (mutating) +// // +// // example: +// // fcpp::set numbers({1, 4, 2}); +// // numbers.remove(4); +// // +// // outcome: +// // numbers -> fcpp::set({1, 2}) +// set& remove(const TKey& element) +// { +// m_map.erase(element); +// return *this; +// } +// +// // Returns a copy by removing an element from the set, if it exists (non-mutating) +// // +// // example: +// // const fcpp::set numbers({1, 4, 2}); +// // auto less_numbers = numbers.removing(4); +// // +// // outcome: +// // less_numbers -> fcpp::set({1, 2}) +// // numbers -> fcpp::set({1, 2, 4}) +// [[nodiscard]] set removing(const TKey& element) const +// { +// auto copy(m_map); +// copy.erase(element); +// return set(copy); +// } +// +// // Inserts an element in the set, if it does not already exist, potentially changing the set's contents (mutating) +// // +// // example: +// // fcpp::set numbers({1, 4, 2}); +// // numbers.insert(18); +// // +// // outcome: +// // numbers -> fcpp::set({1, 2, 4, 18}) +// set& insert(const TKey& element) +// { +// m_map.insert(element); +// return *this; +// } +// +// // Returns a copy by inserting an element in the set, if it does not already exist (non-mutating) +// // +// // example: +// // const fcpp::set numbers({1, 4, 2}); +// // auto augmented_numbers = numbers.inserting(18); +// // +// // outcome: +// // augmented_numbers -> fcpp::set({1, 2, 4, 18}) +// // numbers -> fcpp::set({1, 2, 4}) +// [[nodiscard]] set inserting(const TKey& element) const +// { +// auto copy(m_map); +// copy.insert(element); +// return set(copy); +// } +// +// // Removes all keys from the set (mutating) +// // +// // example: +// // fcpp::set numbers({1, 4, 2}); +// // numbers.clear(); +// // +// // outcome: +// // numbers -> fcpp::set({}) +// set& clear() +// { +// m_map.clear(); +// return *this; +// } +// +// // Returns a new set by clearing all keys from the current set (non-mutating) +// // +// // example: +// // const fcpp::set numbers({1, 4, 2}); +// // auto cleared_numbers = numbers.clearing(); +// // +// // outcome: +// // cleared_numbers -> fcpp::set({}) +// // numbers -> fcpp::set numbers({1, 4, 2}) +// [[nodiscard]] set clearing() const +// { +// return set(); +// } +// +// // Returns true if the set is empty +// // +// // example: +// // const fcpp::set numbers({1, 4, 2}); +// // +// // // returns false +// // numbers.is_empty(); +// // +// // // returns true +// // fcpp::set().is_empty(); +// [[nodiscard]] bool is_empty() const +// { +// return m_map.empty(); +// } +// +// +// // Returns true if the key is present in the set, otherwise false +// // +// // example: +// // const fcpp::set numbers({1, 4, 2}); +// // numbers.contains(1); // true +// // numbers.contains(15); // false +// [[nodiscard]] bool contains(const TKey& key) const +// { +// return m_map.count(key) != 0; +// } +// + // Returns the size of the map (how many elements it contains, it may be different from its capacity) + [[nodiscard]] size_t size() const + { + return m_map.size(); + } +// +// // Returns the begin iterator, useful for other standard library algorithms +// [[nodiscard]] typename std::set::iterator begin() +// { +// return m_map.begin(); +// } +// +// // Returns the const begin iterator, useful for other standard library algorithms +// [[nodiscard]] typename std::set::const_iterator begin() const +// { +// return m_map.begin(); +// } +// +// // Returns the end iterator, useful for other standard library algorithms +// [[nodiscard]] typename std::set::iterator end() +// { +// return m_map.end(); +// } +// +// // Returns the const end iterator, useful for other standard library algorithms +// [[nodiscard]] typename std::set::const_iterator end() const +// { +// return m_map.end(); +// } +// +// // Returns the given key in the current set, allowing subscripting. +// // Bounds checking (assert) is enabled for debug builds. +// // Performance is O(n), so be careful for performance critical code sections. +// TKey operator[](size_t index) +// { +// assert_smaller_size(index); +//#ifdef CPP17_AVAILABLE +// auto it = std::advance(begin(), index); +// return *it; +//#else +// auto count = 0; +// auto it = begin(); +// while (count++ < index) { +// it++; +// } +// return *it; +//#endif +// } +// +// // Returns the given key in the current constant set, allowing subscripting. +// // Bounds checking (assert) is enabled for debug builds. +// // Performance is O(n), so be careful for performance critical code sections. +// TKey operator[](size_t index) const +// { +// assert_smaller_size(index); +//#ifdef CPP17_AVAILABLE +// auto it = begin(); +// std::advance(it, index); +// return *it; +//#else +// auto count = 0; +// auto it = begin(); +// while (count++ < index) { +// it++; +// } +// return *it; +//#endif +// } +// +// // Returns true if both instances have equal sizes and the corresponding elements (keys) are equal +// bool operator ==(const set& rhs) const +// { +//#ifdef CPP17_AVAILABLE +// return std::equal(begin(), +// end(), +// rhs.begin(), +// rhs.end()); +//#else +// if (size() != rhs.size()) { +// return false; +// } +// +// auto it1 = begin(); +// auto it2 = rhs.begin(); +// while (it1 != end() && it2 != rhs.end()) { +// if (!(*it1 == *it2)) { +// return false; +// } +// it1++; +// it2++; +// } +// +// return true; +//#endif +// } +// +// // Returns false if either the sizes are not equal or at least one corresponding element (key) is not equal +// bool operator !=(const set& rhs) const +// { +// return !((*this) == rhs); +// } +// +private: + std::map m_map; +// +// void assert_smaller_size(const size_t index) const +// { +// assert(index < size()); +// } +// +//#ifdef CPP17_AVAILABLE +// template::value>> +// [[nodiscard]] auto zip_impl( const Iterator& set_begin, const Iterator& set_end) const -> +// set>> +// { +// using UKey = deref_type; +//#else +// template +// [[nodiscard]] set> zip_impl(const typename std::set::const_iterator& set_begin, +// const typename std::set::const_iterator& set_end) const +// { +//#endif +// const auto vec_size = std::distance(set_begin, set_end); +// assert(size() == vec_size); +// std::set> combined_set; +// auto it1 = begin(); +// auto it2 = set_begin; +// for (; it1 != end() && it2 != set_end; it1++, it2++) { +// combined_set.insert({*it1, *it2}); +// } +// return set>(combined_set); +// } +}; + +} diff --git a/include/set.h b/include/set.h index 758f892..d978a8c 100644 --- a/include/set.h +++ b/include/set.h @@ -35,7 +35,7 @@ class vector; // of the standard library algorithms. // // Member functions can be mutating (eg. my_set.insert()) or -// non-mutating (eg. my_vector.inserting()) enforcing thread safety if needed +// non-mutating (eg. my_set.inserting()) enforcing thread safety if needed template > class set { @@ -184,7 +184,7 @@ class set // output of applying the transform function on every element of this instance. // // example: - // const fcpp::vector input_set({ 1, 3, -5 }); + // const fcpp::set input_set({ 1, 3, -5 }); // const auto output_set = input_set.map([](const int& element) { // return std::to_string(element); // }); @@ -291,7 +291,7 @@ class set } // Performs the functional `reduce` (fold/accumulate) algorithm, by returning the result of - // accumulating all the values in the vector to an initial value. (non-mutating) + // accumulating all the values in the set to an initial value. (non-mutating) // // example: // const fcpp::set tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" }); @@ -590,7 +590,7 @@ class set return m_set.count(key) != 0; } - // Returns the size of the vector (how many elements it contains, it may be different from its capacity) + // Returns the size of the set (how many elements it contains, it may be different from its capacity) [[nodiscard]] size_t size() const { return m_set.size(); diff --git a/tests/map_test.cc b/tests/map_test.cc new file mode 100644 index 0000000..631b616 --- /dev/null +++ b/tests/map_test.cc @@ -0,0 +1,36 @@ +// MIT License +// +// Copyright (c) 2023 Ioannis Kaliakatsos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include +#include "warnings.h" +#include "map.h" +#include "vector.h" +#include "test_types.h" +#include + +using namespace fcpp; + +TEST(MapTest, EmptyConstructor) +{ + const map map_under_test; + EXPECT_EQ(0, map_under_test.size()); +} From f51b304b8fdca708b7f453b9f7a5dd181e9e29de Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 24 Sep 2023 16:36:29 +0200 Subject: [PATCH 02/11] StdMapConstructor --- include/map.h | 100 +++------ tests/map_test.cc | 527 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 562 insertions(+), 65 deletions(-) diff --git a/include/map.h b/include/map.h index c798c9e..5387005 100644 --- a/include/map.h +++ b/include/map.h @@ -42,8 +42,8 @@ class map { } - explicit map(std::set set) - : m_map(std::move(set)) + explicit map(std::map map) + : m_map(std::move(map)) { } @@ -592,69 +592,39 @@ class map { return m_map.size(); } -// -// // Returns the begin iterator, useful for other standard library algorithms -// [[nodiscard]] typename std::set::iterator begin() -// { -// return m_map.begin(); -// } -// -// // Returns the const begin iterator, useful for other standard library algorithms -// [[nodiscard]] typename std::set::const_iterator begin() const -// { -// return m_map.begin(); -// } -// -// // Returns the end iterator, useful for other standard library algorithms -// [[nodiscard]] typename std::set::iterator end() -// { -// return m_map.end(); -// } -// -// // Returns the const end iterator, useful for other standard library algorithms -// [[nodiscard]] typename std::set::const_iterator end() const -// { -// return m_map.end(); -// } -// -// // Returns the given key in the current set, allowing subscripting. -// // Bounds checking (assert) is enabled for debug builds. -// // Performance is O(n), so be careful for performance critical code sections. -// TKey operator[](size_t index) -// { -// assert_smaller_size(index); -//#ifdef CPP17_AVAILABLE -// auto it = std::advance(begin(), index); -// return *it; -//#else -// auto count = 0; -// auto it = begin(); -// while (count++ < index) { -// it++; -// } -// return *it; -//#endif -// } -// -// // Returns the given key in the current constant set, allowing subscripting. -// // Bounds checking (assert) is enabled for debug builds. -// // Performance is O(n), so be careful for performance critical code sections. -// TKey operator[](size_t index) const -// { -// assert_smaller_size(index); -//#ifdef CPP17_AVAILABLE -// auto it = begin(); -// std::advance(it, index); -// return *it; -//#else -// auto count = 0; -// auto it = begin(); -// while (count++ < index) { -// it++; -// } -// return *it; -//#endif -// } + + // Returns the begin iterator, useful for other standard library algorithms + [[nodiscard]] typename std::map::iterator begin() + { + return m_map.begin(); + } + + // Returns the const begin iterator, useful for other standard library algorithms + [[nodiscard]] typename std::map::const_iterator begin() const + { + return m_map.begin(); + } + + // Returns the end iterator, useful for other standard library algorithms + [[nodiscard]] typename std::map::iterator end() + { + return m_map.end(); + } + + // Returns the const end iterator, useful for other standard library algorithms + [[nodiscard]] typename std::map::const_iterator end() const + { + return m_map.end(); + } + + // Returns the value for the given key in the current map. + // It asserts that the given key is present in the map. + const TValue& operator[](TKey key) const + { + auto it = m_map.find(key); + assert(it != end()); + return (*it).second; + } // // // Returns true if both instances have equal sizes and the corresponding elements (keys) are equal // bool operator ==(const set& rhs) const diff --git a/tests/map_test.cc b/tests/map_test.cc index 631b616..e537db0 100644 --- a/tests/map_test.cc +++ b/tests/map_test.cc @@ -29,8 +29,535 @@ using namespace fcpp; +void test_contents(const map& map) { + EXPECT_EQ(3, map.size()); + EXPECT_EQ(std::string("one"), map[1]); + EXPECT_EQ(std::string("two"), map[2]); + EXPECT_EQ(std::string("three"), map[3]); +} + TEST(MapTest, EmptyConstructor) { const map map_under_test; EXPECT_EQ(0, map_under_test.size()); } + +TEST(MapTest, StdMapConstructor) +{ + const map map_under_test(std::map{{1, "one"}, {2, "two"}, {3, "three"}}); + test_contents(map_under_test); +} + +//TEST(MapTest, StdVectorConstructor) +//{ +// const set set_under_test(std::vector({1, 5, 3, 3})); +// test_contents(set_under_test); +//} +// +//TEST(MapTest, FunctionalVectorConstructor) +//{ +// const set set_under_test(vector({1, 5, 3, 3})); +// test_contents(set_under_test); +//} +// +//TEST(MapTest, StdInitializerListConstructor) +//{ +// const set set_under_test(std::initializer_list({1, 5, 3, 3})); +// test_contents(set_under_test); +//} +// +//TEST(MapTest, Subscripting) +//{ +// const set set_under_test(std::set({1, 5, 3, 3})); +// test_contents(set_under_test); +//} +// +//TEST(MapTest, ConstSubscripting) +//{ +// const set set_under_test(std::set({1, 5, 3, 3})); +// test_contents(set_under_test); +//} +// +//TEST(MapTest, Difference) +//{ +// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// const set set2(std::set({2, 5, 7, 10, 15, 17})); +// const auto& diff = set1.difference_with(set2); +// EXPECT_EQ(set({1, 3, 8}), diff); +//} +// +//TEST(MapTest, DifferenceStdSet) +//{ +// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// const std::set set2({2, 5, 7, 10, 15, 17}); +// const auto& diff = set1.difference_with(set2); +// EXPECT_EQ(set({1, 3, 8}), diff); +//} +// +//TEST(MapTest, DifferenceFunctionalSet) +//{ +// const set set1({1, 2, 3, 5, 7, 8, 10}); +// const set set2({2, 5, 7, 10, 15, 17}); +// const auto& diff = set1.difference_with(set2); +// EXPECT_EQ(set({1, 3, 8}), diff); +//} +// +//TEST(MapTest, DifferenceFunctionalSetCustomType) +//{ +// const set set1({ +// person(51, "George"), +// person(81, "Jackie"), +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate") +// }); +// +// const set set2({ +// person(51, "George"), +// person(81, "Jackie"), +// }); +// +// const auto& diff = set1.difference_with(set2); +// +// const set expected({ +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate") +// }); +// +// EXPECT_EQ(expected, diff); +//} +// +//TEST(MapTest, Union) +//{ +// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// const set set2(std::set({2, 5, 7, 10, 15, 17})); +// const auto& combined = set1.union_with(set2); +// EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); +//} +// +//TEST(MapTest, UnionStdSet) +//{ +// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// const std::set set2({2, 5, 7, 10, 15, 17}); +// const auto& combined = set1.union_with(set2); +// EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); +//} +// +//TEST(MapTest, UnionFunctionalSet) +//{ +// const set set1({1, 2, 3, 5, 7, 8, 10}); +// const set set2({2, 5, 7, 10, 15, 17}); +// const auto& combined = set1.union_with(set2); +// EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); +//} +// +//TEST(MapTest, UnionFunctionalSetCustomType) +//{ +// const set set1({ +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate") +// }); +// +// const set set2({ +// person(51, "George"), +// person(81, "Jackie"), +// }); +// +// const auto& combined = set1.union_with(set2); +// +// const set expected({ +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate"), +// person(51, "George"), +// person(81, "Jackie"), +// }); +// +// EXPECT_EQ(expected, combined); +//} +// +//TEST(MapTest, Intersection) +//{ +// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// const set set2(std::set({2, 5, 7, 10, 15, 17})); +// const auto& intersection = set1.intersect_with(set2); +// EXPECT_EQ(set({2, 5, 7, 10}), intersection); +//} +// +//TEST(MapTest, IntersectionStdSet) +//{ +// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); +// const std::set set2({2, 5, 7, 10, 15, 17}); +// const auto& intersection = set1.intersect_with(set2); +// EXPECT_EQ(set({2, 5, 7, 10}), intersection); +//} +// +//TEST(MapTest, IntersectionFunctionalSet) +//{ +// const set set1({1, 2, 3, 5, 7, 8, 10}); +// const set set2({2, 5, 7, 10, 15, 17}); +// const auto& intersection = set1.intersect_with(set2); +// EXPECT_EQ(set({2, 5, 7, 10}), intersection); +//} +// +//TEST(MapTest, IntersectionFunctionalSetCustomType) +//{ +// const set set1({ +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate"), +// person(51, "George"), +// person(81, "Jackie"), +// }); +// +// const set set2({ +// person(39, "Robert"), +// person(18, "Jannet"), +// person(25, "Kate"), +// person(52, "Anna"), +// person(63, "Simon"), +// }); +// +// const auto& intersection = set1.intersect_with(set2); +// +// const set expected({ +// person(18, "Jannet"), +// person(25, "Kate"), +// }); +// +// EXPECT_EQ(expected, intersection); +//} +// +//TEST(MapTest, Min) +//{ +// const set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); +// const auto minimum = numbers.min(); +// EXPECT_TRUE(minimum.has_value()); +// EXPECT_EQ(1, minimum.value()); +//} +// +//TEST(MapTest, MinCustomType) +//{ +// const set persons({ +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate"), +// person(62, "Bob") +// }); +// const auto minimum = persons.min(); +//#if defined(__clang__) +// EXPECT_EQ(person(18, "Jannet"), minimum.value()); +//#else +// EXPECT_EQ(person(62, "Bob"), minimum.value()); +//#endif +//} +// +//TEST(MapTest, MinEmptySet) +//{ +// const set numbers; +// const auto minimum = numbers.min(); +// EXPECT_FALSE(minimum.has_value()); +//} +// +//TEST(MapTest, Max) +//{ +// const set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); +// const auto maximum = numbers.max(); +// EXPECT_TRUE(maximum.has_value()); +// EXPECT_EQ(8, maximum.value()); +//} +// +//TEST(MapTest, MaxCustomType) +//{ +// const set persons({ +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate"), +// person(62, "Bob") +// }); +// const auto maximum = persons.max(); +// std::cout << maximum.value().name << std::endl; +//#if __linux__ // NOLINT(clang-diagnostic-undef) +// EXPECT_EQ(person(18, "Jannet"), maximum.value()); +//#else +// EXPECT_EQ(person(25, "Kate"), maximum.value()); +//#endif +//} +// +//TEST(MapTest, MaxEmptySet) +//{ +// const set numbers; +// const auto maximum = numbers.max(); +// EXPECT_FALSE(maximum.has_value()); +//} +// +//TEST(MapTest, Map) +//{ +// const set numbers({4, 1, 3}); +// const auto mapped_set = numbers.map([](const int& age) { +// return child(age); +// }); +// EXPECT_EQ(3, mapped_set.size()); +// EXPECT_EQ(1, mapped_set[0].age); +// EXPECT_EQ(3, mapped_set[1].age); +// EXPECT_EQ(4, mapped_set[2].age); +//} +// +//TEST(MapTest, AllOf) +//{ +// const set numbers({1, 4, 2, 5, 8, 3}); +// EXPECT_TRUE(numbers.all_of([](const int &number) { return number < 10; })); +// EXPECT_FALSE(numbers.all_of([](const int &number) { return number > 2; })); +//} +// +//TEST(MapTest, AnyOf) +//{ +// const set numbers({1, 4, 2, 5, 8, 3}); +// EXPECT_TRUE(numbers.any_of([](const int &number) { return number < 5; })); +// EXPECT_FALSE(numbers.any_of([](const int &number) { return number > 10; })); +//} +// +//TEST(MapTest, NoneOf) +//{ +// const set numbers({1, 4, 2, 5, 8, 3}); +// EXPECT_TRUE(numbers.none_of([](const int &number) { return number > 10; })); +// EXPECT_FALSE(numbers.none_of([](const int &number) { return number < 6; })); +//} +// +//TEST(MapTest, Reduce) +//{ +// const set tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" }); +// const auto sentence = tokens.reduce(std::string(""), [](const std::string& partial, const std::string& token) { +// return partial.length() != 0 +// ? partial + " " + token +// : token; +// }); +// EXPECT_EQ("brown dog fox jumps lazy over quick the", sentence); +//} +// +//TEST(MapTest, Filter) +//{ +// set numbers({ 1, 3, -5, 2, -1, 9, -4 }); +// numbers.filter([](const int& element) { +// return element >= 1.5; +// }); +// EXPECT_EQ(set({2, 3, 9}), numbers); +//} +// +//TEST(MapTest, Filtered) +//{ +// const set numbers({ 1, 3, -5, 2, -1, 9, -4 }); +// auto filtered_numbers = numbers.filtered([](const int& element) { +// return element >= 1.5; +// }); +// EXPECT_EQ(set({2, 3, 9}), filtered_numbers); +// EXPECT_EQ(set({ 1, 3, -5, 2, -1, 9, -4 }), numbers); +//} +// +//TEST(MapTest, ZipWithFunctionalSet) +//{ +// const set ages({ 25, 45, 30, 63 }); +// const set persons({ "Jake", "Bob", "Michael", "Philipp" }); +// const auto zipped = ages.zip(persons); +// const auto expected = set>({ +// std::pair(25, "Bob"), +// std::pair(30, "Jake"), +// std::pair(45, "Michael"), +// std::pair(63, "Philipp"), +// }); +// EXPECT_EQ(expected, zipped); +//} +// +//TEST(MapTest, ZipWithFunctionalSetDifferentSizes) +//{ +// const set ages({ 25, 45, 30, 63 }); +// const set persons({ "Jake" }); +// EXPECT_DEATH(ages.zip(persons), ""); +//} +// +//TEST(MapTest, ZipWithStdSet) +//{ +// const set ages({ 25, 45, 30, 63 }); +// const std::set persons({ "Jake", "Bob", "Michael", "Philipp" }); +// const auto zipped = ages.zip(persons); +// const auto expected = set>({ +// std::pair(25, "Bob"), +// std::pair(30, "Jake"), +// std::pair(45, "Michael"), +// std::pair(63, "Philipp"), +// }); +// EXPECT_EQ(expected, zipped); +//} +// +//TEST(MapTest, ZipWithStdSetDifferentSizes) +//{ +// const set ages({ 25, 45, 30, 63 }); +// const std::set persons({ "Jake" }); +// EXPECT_DEATH(ages.zip(persons), ""); +//} +// +//TEST(MapTest, ZipWithFunctionalVector) +//{ +// const set ages({ 25, 45, 30, 63 }); +// const vector persons({ "Jake", "Bob", "Michael", "Philipp" }); +// const auto zipped = ages.zip(persons); +// const auto expected = set>({ +// std::pair(25, "Bob"), +// std::pair(30, "Jake"), +// std::pair(45, "Michael"), +// std::pair(63, "Philipp"), +// }); +// EXPECT_EQ(expected, zipped); +//} +// +//TEST(MapTest, ZipWithFunctionalVectorDifferentSizes) +//{ +// const set ages({ 25, 45, 30, 63 }); +// const vector persons({ "Jake" }); +// EXPECT_DEATH(ages.zip(persons), ""); +//} +// +//TEST(MapTest, ZipWithStdVector) +//{ +// const set ages({ 25, 45, 30, 63 }); +// const std::vector persons({ "Jake", "Bob", "Michael", "Philipp" }); +// const auto zipped = ages.zip(persons); +// const auto expected = set>({ +// std::pair(25, "Bob"), +// std::pair(30, "Jake"), +// std::pair(45, "Michael"), +// std::pair(63, "Philipp"), +// }); +// EXPECT_EQ(expected, zipped); +//} +// +//TEST(MapTest, ZipWithStdVectorDifferentSizes) +//{ +// const set ages({ 25, 45, 30, 63 }); +// const std::vector persons({ "Jake" }); +// EXPECT_DEATH(ages.zip(persons), ""); +//} +// +//TEST(MapTest, Keys) +//{ +// const set numbers({ 25, 45, 30, 63 }); +// const auto keys = numbers.keys(); +// EXPECT_EQ(vector({25, 30, 45, 63}), keys); +//} +// +//TEST(MapTest, RemoveExistingElement) +//{ +// set numbers({1, 4, 2}); +// numbers.remove(4); +// EXPECT_EQ(set({1, 2}), numbers); +//} +// +//TEST(MapTest, RemoveNonExistentElement) +//{ +// set numbers({1, 4, 2}); +// numbers.remove(18); +// EXPECT_EQ(set({1, 2, 4}), numbers); +//} +// +//TEST(MapTest, RemovingExistingElement) +//{ +// const set numbers({1, 4, 2}); +// const auto less_numbers = numbers.removing(4); +// EXPECT_EQ(set({1, 2}), less_numbers); +// EXPECT_EQ(set({1, 2, 4}), numbers); +//} +// +//TEST(MapTest, InsertNewElement) +//{ +// set numbers({1, 4, 2}); +// numbers.insert(18); +// EXPECT_EQ(set({1, 2, 4, 18}), numbers); +//} +// +//TEST(MapTest, InsertingNewElement) +//{ +// const set numbers({1, 4, 2}); +// const auto augmented_numbers = numbers.inserting(18); +// EXPECT_EQ(set({1, 2, 4, 18}), augmented_numbers); +// EXPECT_EQ(set({1, 2, 4}), numbers); +//} +// +//TEST(MapTest, InsertExistingElement) +//{ +// set numbers({1, 4, 2}); +// numbers.insert(2); +// EXPECT_EQ(set({1, 2, 4}), numbers); +//} +// +//TEST(MapTest, InsertingExistingElement) +//{ +// const set numbers({1, 4, 2}); +// const auto augmented_numbers = numbers.inserting(2); +// EXPECT_EQ(set({1, 2, 4}), augmented_numbers); +// EXPECT_EQ(set({1, 2, 4}), numbers); +//} +// +//TEST(MapTest, Clear) +//{ +// set numbers({1, 4, 2}); +// numbers.clear(); +// EXPECT_EQ(0, numbers.size()); +//} +// +//TEST(MapTest, Clearing) +//{ +// const set numbers({1, 4, 2}); +// const auto cleared_numbers = numbers.clearing(); +// EXPECT_EQ(0, cleared_numbers.size()); +// EXPECT_EQ(3, numbers.size()); +//} +// +//TEST(MapTest, IsEmpty) +//{ +// const set numbers({1, 4, 2}); +// EXPECT_FALSE(numbers.is_empty()); +// EXPECT_TRUE(set().is_empty()); +//} +// +//TEST(MapTest, Contains) +//{ +// const set numbers({1, 4, 2}); +// EXPECT_TRUE(numbers.contains(1)); +// EXPECT_FALSE(numbers.contains(15)); +//} +// +//TEST(MapTest, EqualityOperator) +//{ +// const set set1(std::set({1, 2, 3})); +// const set set2(std::set({1, 2, 3, 2, 3})); +// EXPECT_TRUE(set1 == set2); +// EXPECT_FALSE(set1 != set2); +//} +// +//TEST(MapTest, InequalityOperator) +//{ +// const set set1(std::set({1, 2, 3})); +// const set set2(std::set({1, 2, 3, 4})); +// EXPECT_FALSE(set1 == set2); +// EXPECT_TRUE(set1 != set2); +//} +// +//TEST(MapTest, EqualityOperatorCustomType) +//{ +// const set set1({ +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate") +// }); +// +// const set set2({ +// person(15, "Jake"), +// person(18, "Jannet"), +// person(25, "Kate") +// }); +// +// EXPECT_TRUE(set1 == set2); +// EXPECT_FALSE(set1 != set2); +//} From b6e9920ddf794b082b968927e3ae9c04662335db Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 24 Sep 2023 16:51:35 +0200 Subject: [PATCH 03/11] InitializerList ctor and is_empty() --- include/map.h | 48 ++++++++++++----------------- tests/map_test.cc | 77 +++++++++-------------------------------------- 2 files changed, 34 insertions(+), 91 deletions(-) diff --git a/include/map.h b/include/map.h index 5387005..32c6388 100644 --- a/include/map.h +++ b/include/map.h @@ -46,21 +46,11 @@ class map : m_map(std::move(map)) { } - -// explicit map(const std::vector& vector) -// : m_map(vector.begin(), vector.end()) -// { -// } -// -// explicit map(const vector& vector) -// : m_map(vector.begin(), vector.end()) -// { -// } -// -// explicit set(const std::initializer_list& list) -// : m_map(list.begin(), list.end()) -// { -// } + + explicit map(const std::initializer_list>& list) + : m_map(list.begin(), list.end()) + { + } // // Returns the set of elements which belong to the current set but not in the other set. // // In Venn diagram notation, if A is the current set and B is the other set, then @@ -560,20 +550,20 @@ class map // return set(); // } // -// // Returns true if the set is empty -// // -// // example: -// // const fcpp::set numbers({1, 4, 2}); -// // -// // // returns false -// // numbers.is_empty(); -// // -// // // returns true -// // fcpp::set().is_empty(); -// [[nodiscard]] bool is_empty() const -// { -// return m_map.empty(); -// } + // Returns true if the map is empty + // + // example: + // const fcpp::map data({{1, "one"}, {2, "two"}, {3, "three"}}); + // + // // returns false + // data.is_empty(); + // + // // returns true + // fcpp::map().is_empty(); + [[nodiscard]] bool is_empty() const + { + return m_map.empty(); + } // // // // Returns true if the key is present in the set, otherwise false diff --git a/tests/map_test.cc b/tests/map_test.cc index e537db0..b2605df 100644 --- a/tests/map_test.cc +++ b/tests/map_test.cc @@ -48,60 +48,12 @@ TEST(MapTest, StdMapConstructor) test_contents(map_under_test); } -//TEST(MapTest, StdVectorConstructor) -//{ -// const set set_under_test(std::vector({1, 5, 3, 3})); -// test_contents(set_under_test); -//} -// -//TEST(MapTest, FunctionalVectorConstructor) -//{ -// const set set_under_test(vector({1, 5, 3, 3})); -// test_contents(set_under_test); -//} -// -//TEST(MapTest, StdInitializerListConstructor) -//{ -// const set set_under_test(std::initializer_list({1, 5, 3, 3})); -// test_contents(set_under_test); -//} -// -//TEST(MapTest, Subscripting) -//{ -// const set set_under_test(std::set({1, 5, 3, 3})); -// test_contents(set_under_test); -//} -// -//TEST(MapTest, ConstSubscripting) -//{ -// const set set_under_test(std::set({1, 5, 3, 3})); -// test_contents(set_under_test); -//} -// -//TEST(MapTest, Difference) -//{ -// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// const set set2(std::set({2, 5, 7, 10, 15, 17})); -// const auto& diff = set1.difference_with(set2); -// EXPECT_EQ(set({1, 3, 8}), diff); -//} -// -//TEST(MapTest, DifferenceStdSet) -//{ -// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// const std::set set2({2, 5, 7, 10, 15, 17}); -// const auto& diff = set1.difference_with(set2); -// EXPECT_EQ(set({1, 3, 8}), diff); -//} -// -//TEST(MapTest, DifferenceFunctionalSet) -//{ -// const set set1({1, 2, 3, 5, 7, 8, 10}); -// const set set2({2, 5, 7, 10, 15, 17}); -// const auto& diff = set1.difference_with(set2); -// EXPECT_EQ(set({1, 3, 8}), diff); -//} -// +TEST(MapTest, StdInitializerListConstructor) +{ + const map map_under_test({{1, "one"}, {2, "two"}, {3, "three"}}); + test_contents(map_under_test); +} + //TEST(MapTest, DifferenceFunctionalSetCustomType) //{ // const set set1({ @@ -513,14 +465,15 @@ TEST(MapTest, StdMapConstructor) // EXPECT_EQ(0, cleared_numbers.size()); // EXPECT_EQ(3, numbers.size()); //} -// -//TEST(MapTest, IsEmpty) -//{ -// const set numbers({1, 4, 2}); -// EXPECT_FALSE(numbers.is_empty()); -// EXPECT_TRUE(set().is_empty()); -//} -// + +TEST(MapTest, IsEmpty) +{ + const map data({{1, "one"}, {2, "two"}, {3, "three"}}); + EXPECT_FALSE(data.is_empty()); + map empty_map; + EXPECT_TRUE(empty_map.is_empty()); +} + //TEST(MapTest, Contains) //{ // const set numbers({1, 4, 2}); From e79df1c419cfba75886c96371d5b207aa36256c6 Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 24 Sep 2023 19:35:34 +0200 Subject: [PATCH 04/11] access operator --- include/map.h | 15 +++++++++++---- tests/map_test.cc | 12 ++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/map.h b/include/map.h index 32c6388..fb38d67 100644 --- a/include/map.h +++ b/include/map.h @@ -607,15 +607,22 @@ class map return m_map.end(); } - // Returns the value for the given key in the current map. - // It asserts that the given key is present in the map. - const TValue& operator[](TKey key) const + // Returns a reference to the value that is mapped to a key, + // assuming that such key already exists. + const TValue& operator[](const TKey& key) const { auto it = m_map.find(key); assert(it != end()); return (*it).second; } -// + + // Returns a reference to the value that is mapped to a key, + // performing an insertion if such key does not already exist. + TValue& operator[](const TKey& key) + { + return m_map[key]; + } +// // // Returns true if both instances have equal sizes and the corresponding elements (keys) are equal // bool operator ==(const set& rhs) const // { diff --git a/tests/map_test.cc b/tests/map_test.cc index b2605df..28380d0 100644 --- a/tests/map_test.cc +++ b/tests/map_test.cc @@ -54,6 +54,18 @@ TEST(MapTest, StdInitializerListConstructor) test_contents(map_under_test); } +TEST(MapTest, AccessConstOperator) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + EXPECT_EQ(32, persons["jake"]); +} + +TEST(MapTest, AccessOperator) +{ + map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + EXPECT_EQ(0, persons["john"]); +} + //TEST(MapTest, DifferenceFunctionalSetCustomType) //{ // const set set1({ From d70521cbeafc6e9e994d499b08600917cfec0167 Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 24 Sep 2023 19:41:41 +0200 Subject: [PATCH 05/11] clear --- include/map.h | 42 ++++++++++++++---------------------------- tests/map_test.cc | 28 ++++++++++------------------ 2 files changed, 24 insertions(+), 46 deletions(-) diff --git a/include/map.h b/include/map.h index fb38d67..2c79f16 100644 --- a/include/map.h +++ b/include/map.h @@ -522,34 +522,20 @@ class map // return set(copy); // } // -// // Removes all keys from the set (mutating) -// // -// // example: -// // fcpp::set numbers({1, 4, 2}); -// // numbers.clear(); -// // -// // outcome: -// // numbers -> fcpp::set({}) -// set& clear() -// { -// m_map.clear(); -// return *this; -// } -// -// // Returns a new set by clearing all keys from the current set (non-mutating) -// // -// // example: -// // const fcpp::set numbers({1, 4, 2}); -// // auto cleared_numbers = numbers.clearing(); -// // -// // outcome: -// // cleared_numbers -> fcpp::set({}) -// // numbers -> fcpp::set numbers({1, 4, 2}) -// [[nodiscard]] set clearing() const -// { -// return set(); -// } -// + // Removes all key/value pairs from the map (mutating) + // + // example: + // map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // persons.clear(); + // + // outcome: + // persons -> fcpp::map{{}} + map& clear() + { + m_map.clear(); + return *this; + } + // Returns true if the map is empty // // example: diff --git a/tests/map_test.cc b/tests/map_test.cc index 28380d0..080809f 100644 --- a/tests/map_test.cc +++ b/tests/map_test.cc @@ -31,9 +31,9 @@ using namespace fcpp; void test_contents(const map& map) { EXPECT_EQ(3, map.size()); - EXPECT_EQ(std::string("one"), map[1]); - EXPECT_EQ(std::string("two"), map[2]); - EXPECT_EQ(std::string("three"), map[3]); + EXPECT_EQ("one", map[1]); + EXPECT_EQ("two", map[2]); + EXPECT_EQ("three", map[3]); } TEST(MapTest, EmptyConstructor) @@ -462,21 +462,13 @@ TEST(MapTest, AccessOperator) // EXPECT_EQ(set({1, 2, 4}), augmented_numbers); // EXPECT_EQ(set({1, 2, 4}), numbers); //} -// -//TEST(MapTest, Clear) -//{ -// set numbers({1, 4, 2}); -// numbers.clear(); -// EXPECT_EQ(0, numbers.size()); -//} -// -//TEST(MapTest, Clearing) -//{ -// const set numbers({1, 4, 2}); -// const auto cleared_numbers = numbers.clearing(); -// EXPECT_EQ(0, cleared_numbers.size()); -// EXPECT_EQ(3, numbers.size()); -//} + +TEST(MapTest, Clear) +{ + map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + persons.clear(); + EXPECT_EQ(0, persons.size()); +} TEST(MapTest, IsEmpty) { From 12b4d80723e4cf98c747aa0bb5219a40c8328186 Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 24 Sep 2023 20:44:59 +0200 Subject: [PATCH 06/11] contains --- include/map.h | 26 +++++++++++++------------- tests/map_test.cc | 14 +++++++------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/map.h b/include/map.h index 2c79f16..b1fdfad 100644 --- a/include/map.h +++ b/include/map.h @@ -550,19 +550,19 @@ class map { return m_map.empty(); } -// -// -// // Returns true if the key is present in the set, otherwise false -// // -// // example: -// // const fcpp::set numbers({1, 4, 2}); -// // numbers.contains(1); // true -// // numbers.contains(15); // false -// [[nodiscard]] bool contains(const TKey& key) const -// { -// return m_map.count(key) != 0; -// } -// + + + // Returns true if the key is present in the map, otherwise false + // + // example: + // const fcpp::map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // persons.contains("jake"); // true + // persons.contains("bob"); // false + [[nodiscard]] bool contains(const TKey& key) const + { + return m_map.find(key) != end(); + } + // Returns the size of the map (how many elements it contains, it may be different from its capacity) [[nodiscard]] size_t size() const { diff --git a/tests/map_test.cc b/tests/map_test.cc index 080809f..fb3ece7 100644 --- a/tests/map_test.cc +++ b/tests/map_test.cc @@ -478,13 +478,13 @@ TEST(MapTest, IsEmpty) EXPECT_TRUE(empty_map.is_empty()); } -//TEST(MapTest, Contains) -//{ -// const set numbers({1, 4, 2}); -// EXPECT_TRUE(numbers.contains(1)); -// EXPECT_FALSE(numbers.contains(15)); -//} -// +TEST(MapTest, Contains) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + EXPECT_TRUE(persons.contains("jake")); + EXPECT_FALSE(persons.contains("bob")); +} + //TEST(MapTest, EqualityOperator) //{ // const set set1(std::set({1, 2, 3})); From f16760ecdbfa08394df721d8206da6d10bea70ce Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 24 Sep 2023 20:50:46 +0200 Subject: [PATCH 07/11] removed some tests --- tests/map_test.cc | 191 ---------------------------------------------- 1 file changed, 191 deletions(-) diff --git a/tests/map_test.cc b/tests/map_test.cc index fb3ece7..6504aa6 100644 --- a/tests/map_test.cc +++ b/tests/map_test.cc @@ -66,197 +66,6 @@ TEST(MapTest, AccessOperator) EXPECT_EQ(0, persons["john"]); } -//TEST(MapTest, DifferenceFunctionalSetCustomType) -//{ -// const set set1({ -// person(51, "George"), -// person(81, "Jackie"), -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate") -// }); -// -// const set set2({ -// person(51, "George"), -// person(81, "Jackie"), -// }); -// -// const auto& diff = set1.difference_with(set2); -// -// const set expected({ -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate") -// }); -// -// EXPECT_EQ(expected, diff); -//} -// -//TEST(MapTest, Union) -//{ -// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// const set set2(std::set({2, 5, 7, 10, 15, 17})); -// const auto& combined = set1.union_with(set2); -// EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); -//} -// -//TEST(MapTest, UnionStdSet) -//{ -// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// const std::set set2({2, 5, 7, 10, 15, 17}); -// const auto& combined = set1.union_with(set2); -// EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); -//} -// -//TEST(MapTest, UnionFunctionalSet) -//{ -// const set set1({1, 2, 3, 5, 7, 8, 10}); -// const set set2({2, 5, 7, 10, 15, 17}); -// const auto& combined = set1.union_with(set2); -// EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); -//} -// -//TEST(MapTest, UnionFunctionalSetCustomType) -//{ -// const set set1({ -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate") -// }); -// -// const set set2({ -// person(51, "George"), -// person(81, "Jackie"), -// }); -// -// const auto& combined = set1.union_with(set2); -// -// const set expected({ -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate"), -// person(51, "George"), -// person(81, "Jackie"), -// }); -// -// EXPECT_EQ(expected, combined); -//} -// -//TEST(MapTest, Intersection) -//{ -// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// const set set2(std::set({2, 5, 7, 10, 15, 17})); -// const auto& intersection = set1.intersect_with(set2); -// EXPECT_EQ(set({2, 5, 7, 10}), intersection); -//} -// -//TEST(MapTest, IntersectionStdSet) -//{ -// const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// const std::set set2({2, 5, 7, 10, 15, 17}); -// const auto& intersection = set1.intersect_with(set2); -// EXPECT_EQ(set({2, 5, 7, 10}), intersection); -//} -// -//TEST(MapTest, IntersectionFunctionalSet) -//{ -// const set set1({1, 2, 3, 5, 7, 8, 10}); -// const set set2({2, 5, 7, 10, 15, 17}); -// const auto& intersection = set1.intersect_with(set2); -// EXPECT_EQ(set({2, 5, 7, 10}), intersection); -//} -// -//TEST(MapTest, IntersectionFunctionalSetCustomType) -//{ -// const set set1({ -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate"), -// person(51, "George"), -// person(81, "Jackie"), -// }); -// -// const set set2({ -// person(39, "Robert"), -// person(18, "Jannet"), -// person(25, "Kate"), -// person(52, "Anna"), -// person(63, "Simon"), -// }); -// -// const auto& intersection = set1.intersect_with(set2); -// -// const set expected({ -// person(18, "Jannet"), -// person(25, "Kate"), -// }); -// -// EXPECT_EQ(expected, intersection); -//} -// -//TEST(MapTest, Min) -//{ -// const set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); -// const auto minimum = numbers.min(); -// EXPECT_TRUE(minimum.has_value()); -// EXPECT_EQ(1, minimum.value()); -//} -// -//TEST(MapTest, MinCustomType) -//{ -// const set persons({ -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate"), -// person(62, "Bob") -// }); -// const auto minimum = persons.min(); -//#if defined(__clang__) -// EXPECT_EQ(person(18, "Jannet"), minimum.value()); -//#else -// EXPECT_EQ(person(62, "Bob"), minimum.value()); -//#endif -//} -// -//TEST(MapTest, MinEmptySet) -//{ -// const set numbers; -// const auto minimum = numbers.min(); -// EXPECT_FALSE(minimum.has_value()); -//} -// -//TEST(MapTest, Max) -//{ -// const set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); -// const auto maximum = numbers.max(); -// EXPECT_TRUE(maximum.has_value()); -// EXPECT_EQ(8, maximum.value()); -//} -// -//TEST(MapTest, MaxCustomType) -//{ -// const set persons({ -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate"), -// person(62, "Bob") -// }); -// const auto maximum = persons.max(); -// std::cout << maximum.value().name << std::endl; -//#if __linux__ // NOLINT(clang-diagnostic-undef) -// EXPECT_EQ(person(18, "Jannet"), maximum.value()); -//#else -// EXPECT_EQ(person(25, "Kate"), maximum.value()); -//#endif -//} -// -//TEST(MapTest, MaxEmptySet) -//{ -// const set numbers; -// const auto maximum = numbers.max(); -// EXPECT_FALSE(maximum.has_value()); -//} -// //TEST(MapTest, Map) //{ // const set numbers({4, 1, 3}); From fa44296690ed34f091a32c3b0ca5cf847031f47a Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 19 Apr 2026 14:26:13 +0200 Subject: [PATCH 08/11] Finalized map implementation --- LICENSE | 2 +- README.md | 112 ++++ include/compatibility.h | 2 +- include/export_def.h | 2 +- include/index_range.h | 2 +- include/map.h | 1035 +++++++++++++++++-------------------- include/optional.h | 2 +- include/set.h | 2 +- include/vector.h | 2 +- src/index_range.cc | 2 +- tests/index_range_test.cc | 2 +- tests/map_test.cc | 432 +++++++--------- tests/optional_test.cc | 2 +- tests/set_test.cc | 2 +- tests/test_types.h | 2 +- tests/vector_test.cc | 2 +- tests/warnings.h | 2 +- 17 files changed, 781 insertions(+), 826 deletions(-) diff --git a/LICENSE b/LICENSE index 5df5b63..01dd2b2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Ioannis Kaliakatsos +Copyright (c) 2026 Ioannis Kaliakatsos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 2240403..9ed9c6f 100644 --- a/README.md +++ b/README.md @@ -273,6 +273,118 @@ any_of_parallel none_of_parallel ``` +## Functional map usage (fcpp::map) +### map_keys, map_values, map_to, filter, reduce, for_each +```c++ +#include "map.h" // instead of + +const fcpp::map ages({ + {"jake", 32}, + {"mary", 26}, + {"david", 40} +}); + +const auto adults = ages + // keep only key/value pairs matching the predicate + .filtered([](const std::pair& element) { + return element.second >= 32; + }); + +// initials -> fcpp::vector({'d', 'j'}) +const auto initials = adults.map_keys([](const std::string& name) { + return name[0]; +}); + +// labels -> fcpp::vector({"40 years", "32 years"}) +const auto labels = adults.map_values([](const int& age) { + return std::to_string(age) + " years"; +}); + +// ages_by_initial -> fcpp::map({{'d', "40 years"}, {'j', "32 years"}}) +const auto ages_by_initial = adults.map_to([](const std::pair& element) { + return std::make_pair(element.first[0], std::to_string(element.second) + " years"); +}); + +// total_age = 72 +const auto total_age = adults.reduce(0, [](const int& partial_sum, const std::pair& element) { + return partial_sum + element.second; +}); + +adults.for_each([](const std::pair& element) { + std::cout << element.first << " is " << element.second << " years old." << std::endl; +}); +``` + +### all_of, any_of, none_of +```c++ +#include "map.h" // instead of + +const fcpp::map ages({ + {"jake", 32}, + {"mary", 26}, + {"david", 40} +}); + +// returns true +ages.all_of([](const std::pair& element) { + return element.second > 20; +}); + +// returns false +ages.all_of([](const std::pair& element) { + return element.second < 35; +}); + +// returns true +ages.any_of([](const std::pair& element) { + return element.second == 40; +}); + +// returns false +ages.any_of([](const std::pair& element) { + return element.second > 50; +}); + +// returns true +ages.none_of([](const std::pair& element) { + return element.second < 18; +}); + +// returns false +ages.none_of([](const std::pair& element) { + return element.second == 26; +}); +``` + +### keys, values, remove, insert +```c++ +#include "map.h" // instead of + +fcpp::map ages({ + {"jake", 32}, + {"mary", 26}, + {"david", 40} +}); + +// names -> fcpp::vector({"david", "jake", "mary"}) +const auto names = ages.keys(); + +// years -> fcpp::vector({40, 32, 26}) +const auto years = ages.values(); + +// ages -> fcpp::map({{"david", 40}, {"jake", 32}}) +ages.remove("mary"); + +// ages -> fcpp::map({{"anna", 28}, {"david", 40}, {"jake", 32}}) +ages.insert("anna", 28); + +// without_jake -> fcpp::map({{"anna", 28}, {"david", 40}}) +const auto without_jake = ages.removing("jake"); + +// with_paul -> fcpp::map({{"anna", 28}, {"david", 40}, {"jake", 32}, {"paul", 51}}) +const auto with_paul = ages.inserting("paul", 51); +``` + ## Functional set usage (fcpp::set) ### difference, union, intersection (works with fcpp::set and std::set) ```c++ diff --git a/include/compatibility.h b/include/compatibility.h index 2554c98..aba6a3b 100644 --- a/include/compatibility.h +++ b/include/compatibility.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/include/export_def.h b/include/export_def.h index 1d15e6e..dcca3a3 100644 --- a/include/export_def.h +++ b/include/export_def.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/include/index_range.h b/include/index_range.h index 37e8f5f..6670939 100644 --- a/include/index_range.h +++ b/include/index_range.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/include/map.h b/include/map.h index b1fdfad..384d0a3 100644 --- a/include/map.h +++ b/include/map.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -22,26 +22,31 @@ #pragma once #include +#include #include -#include "optional.h" +#include +#include +#include "vector.h" namespace fcpp { -template -class vector; - // A lightweight wrapper around std::map, enabling fluent and functional // programming on the map itself, rather than using the more procedural style // of the standard library algorithms. +// +// Member functions can be mutating (eg. my_map.remove("name")) or +// non-mutating (eg. my_map.removing("name")) enforcing thread safety if needed template > class map { public: + using value_type = std::pair; + map() : m_map() { } - + explicit map(std::map map) : m_map(std::move(map)) { @@ -51,627 +56,525 @@ class map : m_map(list.begin(), list.end()) { } - -// // Returns the set of elements which belong to the current set but not in the other set. -// // In Venn diagram notation, if A is the current set and B is the other set, then -// // the difference is the operation A – B = {x : x ∈ A and x ∉ B} -// // -// // example: -// // const fcpp::set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// // const fcpp::set set2(std::set({2, 5, 7, 10, 15, 17})); -// // const auto& diff = set1.difference(set2); -// // -// // outcome: -// // diff -> fcpp::set({1, 3, 8}) -// [[nodiscard]] set difference_with(const set& other) const { -// std::set diff; -// std::set_difference(begin(), -// end(), -// other.begin(), -// other.end(), -// std::inserter(diff, diff.begin())); -// return set(diff); -// } -// -// [[nodiscard]] set difference_with(const std::set& other) const { -// return difference_with(set(other)); -// } -// -// // Returns the set of elements which belong either to the current or the other set. -// // In Venn diagram notation, if A is the current set and B is the other set, then -// // the union is the operation A ∪ B = {x : x ∈ A or x ∈ B} -// // -// // example: -// // const fcpp::set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// // const fcpp::set set2(std::set({2, 5, 7, 10, 15, 17})); -// // const auto& combined = set1.set_union(set2); -// // -// // outcome: -// // combined -> fcpp::set({1, 2, 3, 5, 7, 8, 10, 15, 17}) -// [[nodiscard]] set union_with(const set& other) const { -// std::set combined; -// std::set_union(begin(), -// end(), -// other.begin(), -// other.end(), -// std::inserter(combined, combined.begin())); -// return set(combined); -// } -// -// [[nodiscard]] set union_with(const std::set& other) const { -// return union_with(set(other)); -// } -// -// // Returns the set of elements which belong to both the current and the other set. -// // In Venn diagram notation, if A is the current set and B is the other set, then -// // the intersection is the operation A ∩ B = {x : x ∈ A and x ∈ B} -// // -// // example: -// // const fcpp::set set1(std::set({1, 2, 3, 5, 7, 8, 10})); -// // const fcpp::set set2(std::set({2, 5, 7, 10, 15, 17})); -// // const auto& combined = set1.set_union(set2); -// // -// // outcome: -// // combined -> fcpp::set({2, 5, 7, 10}) -// [[nodiscard]] set intersect_with(const set& other) const { -// std::set intersection; -// std::set_intersection(begin(), -// end(), -// other.begin(), -// other.end(), -// std::inserter(intersection, intersection.begin())); -// return set(intersection); -// } -// -// [[nodiscard]] set intersect_with(const std::set& other) const { -// return intersect_with(set(other)); -// } -// -// // Returns the minimum key in the set, if it's not empty. -// // -// // example: -// // const fcpp::set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); -// // auto minimum = numbers.min(); -// // -// // // an empty's set minimum value -// // fcpp::set().min().has_value() // false -// // -// // outcome: -// // minimum.has_value() -> true -// // minimum.value() -> 1 -// [[nodiscard]] fcpp::optional_t min() const { -// const auto& it = std::min_element(begin(), end()); -// if (it != end()) { -// return *it; -// } -// return fcpp::optional_t(); -// } -// -// // Returns the maximum key in the set, if it's not empty. -// // -// // example: -// // const fcpp::set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); -// // auto maximum = numbers.max(); -// // -// // // an empty's set maximum value -// // fcpp::set().max().has_value() // false -// // -// // outcome: -// // maximum.has_value() -> true -// // maximum.value() -> 8 -// [[nodiscard]] fcpp::optional_t max() const { -// const auto& it = std::max_element(begin(), end()); -// if (it != end()) { -// return *it; -// } -// return fcpp::optional_t(); -// } -// -// // Performs the functional `map` algorithm, in which every element of the resulting set is the -// // output of applying the transform function on every element of this instance. -// // -// // example: -// // const fcpp::vector input_set({ 1, 3, -5 }); -// // const auto output_set = input_set.map([](const int& element) { -// // return std::to_string(element); -// // }); -// // -// // outcome: -// // output_set -> fcpp::set({ "-5", "1", "3" }) -// // -// // is equivalent to: -// // const fcpp::set input_set({ 1, 3, -5 }); -// // fcpp::set output_set; -// // for (auto const& key: input_set) { -// // output_set.insert(std::to_string(key)); -// // } -//#ifdef CPP17_AVAILABLE -// template , typename Transform, typename = std::enable_if_t>> -//#else -// template , typename Transform> -//#endif -// set map(Transform && transform) const -// { -// std::set transformed_set; -// for (const auto& key: m_map) { -// transformed_set.insert(transform(key)); -// } -// return set(transformed_set); -// } -// -// // Returns true if all keys match the predicate (return true) -// // -// // example: -// // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); -// // -// // // returns true -// // numbers.all_of([](const int &number) { -// // return number < 10; -// // }); -// // -// // // returns false -// // numbers.all_of([](const int &number) { -// // return number > 2; -// // }); -//#ifdef CPP17_AVAILABLE -// template >> -//#else -// template -//#endif -// bool all_of(Callable && unary_predicate) const -// { -// return std::all_of(begin(), -// end(), -// std::forward(unary_predicate)); -// } -// -// // Returns true if at least one key match the predicate (returns true) -// // -// // example: -// // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); -// // -// // // returns true -// // numbers.any_of([](const int &number) { -// // return number < 5; -// // }); -// // -// // // returns false -// // numbers.any_of([](const int &number) { -// // return number > 10; -// // }); -//#ifdef CPP17_AVAILABLE -// template >> -//#else -// template -//#endif -// bool any_of(Callable && unary_predicate) const -// { -// return std::any_of(begin(), -// end(), -// std::forward(unary_predicate)); -// } -// -// // Returns true if none of the keys match the predicate (all return false) -// // -// // example: -// // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); -// // -// // // returns true -// // numbers.none_of([](const int &number) { -// // return number > 10; -// // }); -// // -// // // returns false -// // numbers.none_of([](const int &number) { -// // return number < 6; -// // }); -//#ifdef CPP17_AVAILABLE -// template >> -//#else -// template -//#endif -// bool none_of(Callable && unary_predicate) const -// { -// return std::none_of(begin(), -// end(), -// std::forward(unary_predicate)); -// } -// -// // Performs the functional `reduce` (fold/accumulate) algorithm, by returning the result of -// // accumulating all the values in the vector to an initial value. (non-mutating) -// // -// // example: -// // const fcpp::set tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" }); -// // const auto sentence = tokens.reduce("", [](const std::string& partial, const std::string& token) { -// // return partial.length() != 0 -// // ? partial + " " + token -// // : token; -// // }); -// // -// // outcome: (a set does not allow multiple entries, and its elements are internally managed, order can vary) -// // -// // sentence -> std::string("brown dog fox jumps lazy over quick the"); -//#ifdef CPP17_AVAILABLE -// template >> -//#else -// template -//#endif -// U reduce(const U& initial, Reduce&& reduction) const -// { -// auto result = initial; -// for (const auto& x : m_map) -// { -// result = reduction(result, x); -// } -// return result; -// } -// -// // Performs the functional `filter` algorithm, in which all keys of this instance -// // which match the given predicate are kept (mutating) -// // -// // example: -// // fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); -// // numbers.filter([](const int& element) { -// // return element >= 1.5; -// // }); -// // -// // outcome: -// // numbers -> fcpp::set({ 2, 3, 9 }); -// // -// // is equivalent to: -// // fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); -// // for (auto i = 0; i < numbers.size(); ++i) { -// // if (numbers[i] >= 1.5) { -// // continue; -// // } -// // numbers.remove(i); -// // i--; -// // } -//#ifdef CPP17_AVAILABLE -// template >> -//#else -// template -//#endif -// set& filter(Filter && predicate_to_keep) -// { -// std::set copy; -// auto it = begin(); -// for (; it != end(); it++) { -// if (predicate_to_keep(*it)) { -// copy.insert(*it); -// } -// } -// m_map = std::move(copy); -// return *this; -// } -// -// // Performs the functional `filter` algorithm in a copy of this instance, in which all keys -// // of the copy which match the given predicate are kept (non-mutating) -// // -// // example: -// // const fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); -// // auto filtered_numbers = numbers.filtered([](const int& element) { -// // return element >= 1.5; -// // }); -// // -// // outcome: -// // filtered_numbers -> fcpp::set({ 2, 3, 9 }); -// // numbers -> fcpp::set({ 1, 3, -5, 2, -1, 9, -4 }); -//#ifdef CPP17_AVAILABLE -// template >> -//#else -// template -//#endif -// set filtered(Filter && predicate_to_keep) const -// { -// std::set copy; -// auto it = begin(); -// for (; it != end(); it++) { -// if (predicate_to_keep(*it)) { -// copy.insert(*it); -// } -// } -// return set(copy); -// } -// -//#ifdef CPP17_AVAILABLE -// template -// using deref_type = typename std::iterator_traits::value_type; -// -// template -// struct is_valid_iterator { -// static bool const value = std::is_constructible_v>; -// }; -//#endif -// -// // Performs the functional `zip` algorithm, in which every key of the resulting set is a -// // tuple of this instance's key (first) and the second set's key (second). -// // The sizes of the two sets must be equal. -// // -// // example: -// // const fcpp::set ages({ 25, 45, 30, 63 }); -// // const fcpp::set persons({ "Jake", "Bob", "Michael", "Philipp" }); -// // const auto zipped = ages.zip(persons); -// // -// // outcome: -// // zipped -> fcpp::set>({ -// // std::pair(25, "Bob"), -// // std::pair(30, "Jake"), -// // std::pair(45, "Michael"), -// // std::pair(63, "Philipp"), -// // }) -// template -// [[nodiscard]] set> zip(const set& set) const -// { -//#ifdef CPP17_AVAILABLE -// return zip_impl(set.begin(), set.end()); -//#else -// return zip_impl(set.begin(), set.end()); -//#endif -// } -// -// // Performs the functional `zip` algorithm. -// // The number of keys must match the set's size. -// // For more details, see the zip function which accepts a fcpp::set as input. -// template -// [[nodiscard]] set> zip(const std::set& set) const -// { -// return zip(fcpp::set(set)); -// } -// -// // Performs the functional `zip` algorithm by using the unique values of the vector. -// // The number of uniques vector values must match the set's size. -// // For more details, see the zip function which accepts a fcpp::set as input. -// template -// [[nodiscard]] set> zip(const vector& vector) const -// { -// const auto distinct_values = vector.distinct(); -// return zip(distinct_values); -// } -// -// // Performs the functional `zip` algorithm by using the unique values of the vector. -// // The number of uniques vector values must match the set's size. -// // For more details, see the zip function which accepts a fcpp::set as input. -// template -// [[nodiscard]] set> zip(const std::vector& vector) const -// { -// return zip(fcpp::vector(vector)); -// } -// -// // Executes the given operation for each key of the set. -// // The operation must not change the set's contents during execution. -//#ifdef CPP17_AVAILABLE -// template >> -//#else -// template -//#endif -// const set& for_each(Callable && operation) const -// { -// std::for_each(begin(), -// end(), -// std::forward(operation)); -// return *this; -// } -// -// vector keys() const { -// vector vec; -// vec.reserve(size()); -// for_each([&vec](const TKey& key) { -// vec.insert_back(key); -// }); -// return std::move(vec); -// } -// -// // Removes an element from the set, if it exists, potentially changing the set's contents (mutating) -// // -// // example: -// // fcpp::set numbers({1, 4, 2}); -// // numbers.remove(4); -// // -// // outcome: -// // numbers -> fcpp::set({1, 2}) -// set& remove(const TKey& element) -// { -// m_map.erase(element); -// return *this; -// } -// -// // Returns a copy by removing an element from the set, if it exists (non-mutating) -// // -// // example: -// // const fcpp::set numbers({1, 4, 2}); -// // auto less_numbers = numbers.removing(4); -// // -// // outcome: -// // less_numbers -> fcpp::set({1, 2}) -// // numbers -> fcpp::set({1, 2, 4}) -// [[nodiscard]] set removing(const TKey& element) const -// { -// auto copy(m_map); -// copy.erase(element); -// return set(copy); -// } -// -// // Inserts an element in the set, if it does not already exist, potentially changing the set's contents (mutating) -// // -// // example: -// // fcpp::set numbers({1, 4, 2}); -// // numbers.insert(18); -// // -// // outcome: -// // numbers -> fcpp::set({1, 2, 4, 18}) -// set& insert(const TKey& element) -// { -// m_map.insert(element); -// return *this; -// } -// -// // Returns a copy by inserting an element in the set, if it does not already exist (non-mutating) -// // -// // example: -// // const fcpp::set numbers({1, 4, 2}); -// // auto augmented_numbers = numbers.inserting(18); -// // -// // outcome: -// // augmented_numbers -> fcpp::set({1, 2, 4, 18}) -// // numbers -> fcpp::set({1, 2, 4}) -// [[nodiscard]] set inserting(const TKey& element) const -// { -// auto copy(m_map); -// copy.insert(element); -// return set(copy); -// } -// - // Removes all key/value pairs from the map (mutating) + + // Performs the functional `map` algorithm for keys, in which every element of the resulting + // vector is the output of applying the transform function on every key of this instance. // // example: - // map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); - // persons.clear(); + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // const auto initials = ages.map_keys([](const auto& name) { + // return name[0]; + // }); // // outcome: - // persons -> fcpp::map{{}} - map& clear() + // initials -> fcpp::vector({'d', 'j', 'm'}) + // + // is equivalent to: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // fcpp::vector initials; + // for (const auto& element : ages) { + // initials.insert_back(element.first[0]); + // } +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + vector map_keys(Transform && transform) const { - m_map.clear(); - return *this; + vector transformed; + transformed.reserve(size()); + for (const auto& element : m_map) { + transformed.insert_back(transform(element.first)); + } + return transformed; } - - // Returns true if the map is empty + + // Performs the functional `map` algorithm for values, in which every element of the resulting + // vector is the output of applying the transform function on every value of this instance. + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // const auto labels = ages.map_values([](const auto& age) { + // return std::to_string(age); + // }); + // + // outcome: + // labels -> fcpp::vector({"40", "32", "26"}) + // + // is equivalent to: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // fcpp::vector labels; + // for (const auto& element : ages) { + // labels.insert_back(std::to_string(element.second)); + // } +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + vector map_values(Transform && transform) const + { + vector transformed; + transformed.reserve(size()); + for (const auto& element : m_map) { + transformed.insert_back(transform(element.second)); + } + return transformed; + } + + // Performs the functional `map` algorithm from one map to another map, in which every key/value + // pair of the resulting map is the output of applying the transform function on every key/value + // pair of this instance. If two source elements produce equivalent result keys, the first + // transformed key/value pair is kept, following std::map::insert semantics. + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // const auto labels_by_initial = ages.map_to([](const auto& element) { + // return std::make_pair(element.first[0], std::to_string(element.second) + " years"); + // }); + // + // outcome: + // labels_by_initial -> fcpp::map({ + // {'d', "40 years"}, {'j', "32 years"}, {'m', "26 years"} + // }) + // + // is equivalent to: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // fcpp::map labels_by_initial; + // for (const auto& element : ages) { + // labels_by_initial.insert(element.first[0], std::to_string(element.second) + " years"); + // } +#ifdef CPP17_AVAILABLE + template , Transform, value_type>>> +#else + template +#endif + [[nodiscard]] fcpp::map map_to(Transform && transform) const + { + fcpp::map transformed; + for (const auto& element : m_map) { + const auto transformed_element = transform(element); + transformed.insert(transformed_element.first, transformed_element.second); + } + return transformed; + } + + // Returns true if all key/value pairs match the predicate (return true) + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // + // // returns true + // ages.all_of([](const auto& element) { + // return element.second > 20; + // }); + // + // // returns false + // ages.all_of([](const auto& element) { + // return element.second < 35; + // }); +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + bool all_of(Callable && unary_predicate) const + { + return std::all_of(begin(), + end(), + std::forward(unary_predicate)); + } + + // Returns true if at least one key/value pair matches the predicate (returns true) // // example: - // const fcpp::map data({{1, "one"}, {2, "two"}, {3, "three"}}); + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // + // // returns true + // ages.any_of([](const auto& element) { + // return element.second == 40; + // }); // // // returns false - // data.is_empty(); + // ages.any_of([](const auto& element) { + // return element.second > 50; + // }); +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + bool any_of(Callable && unary_predicate) const + { + return std::any_of(begin(), + end(), + std::forward(unary_predicate)); + } + + // Returns true if no key/value pair matches the predicate (all return false) + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); // // // returns true - // fcpp::map().is_empty(); + // ages.none_of([](const auto& element) { + // return element.second < 18; + // }); + // + // // returns false + // ages.none_of([](const auto& element) { + // return element.second == 26; + // }); +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + bool none_of(Callable && unary_predicate) const + { + return std::none_of(begin(), + end(), + std::forward(unary_predicate)); + } + + // Performs the functional `reduce` (fold/accumulate) algorithm, by returning the result of + // accumulating all key/value pairs in the map to an initial value. (non-mutating) + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // const auto total_age = ages.reduce(0, [](const int& partial_sum, const auto& element) { + // return partial_sum + element.second; + // }); + // + // outcome: + // total_age -> 98 +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + U reduce(const U& initial, Reduce&& reduction) const + { + auto result = initial; + for (const auto& x : m_map) + { + result = reduction(result, x); + } + return result; + } + + // Performs the functional `filter` algorithm, in which all key/value pairs of this instance + // which match the given predicate are kept (mutating) + // + // example: + // fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // ages.filter([](const auto& element) { + // return element.second >= 32; + // }); + // + // outcome: + // ages -> fcpp::map({{"david", 40}, {"jake", 32}}) + // + // is equivalent to: + // fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // auto it = ages.begin(); + // while (it != ages.end()) { + // if (it->second >= 32) { + // ++it; + // } else { + // const auto key = it->first; + // ++it; + // ages.remove(key); + // } + // } +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + map& filter(Filter && predicate_to_keep) + { + auto it = begin(); + while (it != end()) { + if (!predicate_to_keep(*it)) { + it = m_map.erase(it); + } else { + ++it; + } + } + return *this; + } + + // Performs the functional `filter` algorithm in a copy of this instance, in which all key/value + // pairs of the copy which match the given predicate are kept (non-mutating) + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // const auto adults = ages.filtered([](const auto& element) { + // return element.second >= 32; + // }); + // + // outcome: + // ages -> fcpp::map({{"david", 40}, {"jake", 32}, {"mary", 26}}) + // adults -> fcpp::map({{"david", 40}, {"jake", 32}}) +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + [[nodiscard]] map filtered(Filter && predicate_to_keep) const + { + auto copy(m_map); + auto it = copy.begin(); + while (it != copy.end()) { + if (!predicate_to_keep(*it)) { + it = copy.erase(it); + } else { + ++it; + } + } + return map(copy); + } + + // Executes the given operation for each key/value pair in the map. The operation must not + // change the map's contents during execution. + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // int total_age = 0; + // ages.for_each([&total_age](const auto& element) { + // total_age += element.second; + // }); + // + // outcome: + // total_age -> 98 +#ifdef CPP17_AVAILABLE + template >> +#else + template +#endif + const map& for_each(Callable && operation) const + { + std::for_each(begin(), + end(), + std::forward(operation)); + return *this; + } + + // Returns a vector whose elements are the map's keys in sorted key order. + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // const auto names = ages.keys(); + // + // outcome: + // names -> fcpp::vector({"david", "jake", "mary"}) + vector keys() const + { + vector vec; + vec.reserve(size()); + for_each([&vec](const value_type& element) { + vec.insert_back(element.first); + }); + return vec; + } + + // Returns a vector whose elements are the map's values in sorted key order. + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // const auto years = ages.values(); + // + // outcome: + // years -> fcpp::vector({40, 32, 26}) + vector values() const + { + vector vec; + vec.reserve(size()); + for_each([&vec](const value_type& element) { + vec.insert_back(element.second); + }); + return vec; + } + + // Removes the element with the given key in place (mutating) + // + // example: + // fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // ages.remove("mary"); + // + // outcome: + // ages -> fcpp::map({{"david", 40}, {"jake", 32}}) + map& remove(const TKey& key) + { + m_map.erase(key); + return *this; + } + + // Returns a copy of this instance without the element with the given key (non-mutating) + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}, {"david", 40}}); + // const auto adults = ages.removing("mary"); + // + // outcome: + // ages -> fcpp::map({{"david", 40}, {"jake", 32}, {"mary", 26}}) + // adults -> fcpp::map({{"david", 40}, {"jake", 32}}) + [[nodiscard]] map removing(const TKey& key) const + { + auto copy(m_map); + copy.erase(key); + return map(copy); + } + + // Inserts a key/value pair in place (mutating). If an equivalent key already exists, the + // existing mapped value is left unchanged, following std::map::insert semantics. + // + // example: + // fcpp::map ages({{"jake", 32}, {"mary", 26}}); + // ages.insert("david", 40); + // + // outcome: + // ages -> fcpp::map({{"david", 40}, {"jake", 32}, {"mary", 26}}) + map& insert(const TKey& key, const TValue& value) + { + m_map.insert(std::make_pair(key, value)); + return *this; + } + + // Inserts a key/value pair in place (mutating). If an equivalent key already exists, the + // existing mapped value is left unchanged, following std::map::insert semantics. + map& insert(const value_type& element) + { + m_map.insert(element); + return *this; + } + + // Returns a copy of this instance with the key/value pair inserted (non-mutating). If an + // equivalent key already exists, the existing mapped value is left unchanged in the returned copy. + // + // example: + // const fcpp::map ages({{"jake", 32}, {"mary", 26}}); + // const auto more_ages = ages.inserting("david", 40); + // + // outcome: + // ages -> fcpp::map({{"jake", 32}, {"mary", 26}}) + // more_ages -> fcpp::map({{"david", 40}, {"jake", 32}, {"mary", 26}}) + [[nodiscard]] map inserting(const TKey& key, const TValue& value) const + { + auto copy(m_map); + copy.insert(std::make_pair(key, value)); + return map(copy); + } + + // Returns a copy of this instance with the key/value pair inserted (non-mutating). If an + // equivalent key already exists, the existing mapped value is left unchanged in the returned copy. + [[nodiscard]] map inserting(const value_type& element) const + { + auto copy(m_map); + copy.insert(element); + return map(copy); + } + + // Removes all key/value pairs from the map (mutating) + map& clear() + { + m_map.clear(); + return *this; + } + + // Returns true if the map is empty [[nodiscard]] bool is_empty() const { return m_map.empty(); } - - + // Returns true if the key is present in the map, otherwise false - // - // example: - // const fcpp::map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); - // persons.contains("jake"); // true - // persons.contains("bob"); // false [[nodiscard]] bool contains(const TKey& key) const { return m_map.find(key) != end(); } - + // Returns the size of the map (how many elements it contains, it may be different from its capacity) [[nodiscard]] size_t size() const { return m_map.size(); } - + // Returns the begin iterator, useful for other standard library algorithms [[nodiscard]] typename std::map::iterator begin() { return m_map.begin(); } - + // Returns the const begin iterator, useful for other standard library algorithms [[nodiscard]] typename std::map::const_iterator begin() const { return m_map.begin(); } - + // Returns the end iterator, useful for other standard library algorithms [[nodiscard]] typename std::map::iterator end() { return m_map.end(); } - + // Returns the const end iterator, useful for other standard library algorithms [[nodiscard]] typename std::map::const_iterator end() const { return m_map.end(); } - + // Returns a reference to the value that is mapped to a key, // assuming that such key already exists. const TValue& operator[](const TKey& key) const { - auto it = m_map.find(key); + const auto it = m_map.find(key); assert(it != end()); return (*it).second; } - + // Returns a reference to the value that is mapped to a key, // performing an insertion if such key does not already exist. TValue& operator[](const TKey& key) { return m_map[key]; } -// -// // Returns true if both instances have equal sizes and the corresponding elements (keys) are equal -// bool operator ==(const set& rhs) const -// { -//#ifdef CPP17_AVAILABLE -// return std::equal(begin(), -// end(), -// rhs.begin(), -// rhs.end()); -//#else -// if (size() != rhs.size()) { -// return false; -// } -// -// auto it1 = begin(); -// auto it2 = rhs.begin(); -// while (it1 != end() && it2 != rhs.end()) { -// if (!(*it1 == *it2)) { -// return false; -// } -// it1++; -// it2++; -// } -// -// return true; -//#endif -// } -// -// // Returns false if either the sizes are not equal or at least one corresponding element (key) is not equal -// bool operator !=(const set& rhs) const -// { -// return !((*this) == rhs); -// } -// + + bool operator ==(const map& rhs) const + { +#ifdef CPP17_AVAILABLE + return std::equal(begin(), + end(), + rhs.begin(), + rhs.end()); +#else + if (size() != rhs.size()) { + return false; + } + + auto it1 = begin(); + auto it2 = rhs.begin(); + while (it1 != end() && it2 != rhs.end()) { + if (!(*it1 == *it2)) { + return false; + } + it1++; + it2++; + } + + return true; +#endif + } + + bool operator !=(const map& rhs) const + { + return !((*this) == rhs); + } + private: std::map m_map; -// -// void assert_smaller_size(const size_t index) const -// { -// assert(index < size()); -// } -// -//#ifdef CPP17_AVAILABLE -// template::value>> -// [[nodiscard]] auto zip_impl( const Iterator& set_begin, const Iterator& set_end) const -> -// set>> -// { -// using UKey = deref_type; -//#else -// template -// [[nodiscard]] set> zip_impl(const typename std::set::const_iterator& set_begin, -// const typename std::set::const_iterator& set_end) const -// { -//#endif -// const auto vec_size = std::distance(set_begin, set_end); -// assert(size() == vec_size); -// std::set> combined_set; -// auto it1 = begin(); -// auto it2 = set_begin; -// for (; it1 != end() && it2 != set_end; it1++, it2++) { -// combined_set.insert({*it1, *it2}); -// } -// return set>(combined_set); -// } }; } diff --git a/include/optional.h b/include/optional.h index 086024e..cb051d0 100644 --- a/include/optional.h +++ b/include/optional.h @@ -1,7 +1,7 @@ // MIT License // // Created by iamOgunyinka on 08 Sep 2021 (@iamOgunyinka, https://github.com/iamOgunyinka) -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/include/set.h b/include/set.h index d978a8c..c414d54 100644 --- a/include/set.h +++ b/include/set.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/include/vector.h b/include/vector.h index d454a2b..3bad6d5 100644 --- a/include/vector.h +++ b/include/vector.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/src/index_range.cc b/src/index_range.cc index 4784abd..ac8ceb4 100644 --- a/src/index_range.cc +++ b/src/index_range.cc @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/tests/index_range_test.cc b/tests/index_range_test.cc index 58ef92d..a6cbc0e 100644 --- a/tests/index_range_test.cc +++ b/tests/index_range_test.cc @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/tests/map_test.cc b/tests/map_test.cc index 6504aa6..ddc3deb 100644 --- a/tests/map_test.cc +++ b/tests/map_test.cc @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,17 +23,15 @@ #include #include "warnings.h" #include "map.h" -#include "vector.h" -#include "test_types.h" #include using namespace fcpp; -void test_contents(const map& map) { - EXPECT_EQ(3, map.size()); - EXPECT_EQ("one", map[1]); - EXPECT_EQ("two", map[2]); - EXPECT_EQ("three", map[3]); +void test_contents(const map& map_under_test) { + EXPECT_EQ(3, map_under_test.size()); + EXPECT_EQ("one", map_under_test[1]); + EXPECT_EQ("two", map_under_test[2]); + EXPECT_EQ("three", map_under_test[3]); } TEST(MapTest, EmptyConstructor) @@ -66,211 +64,171 @@ TEST(MapTest, AccessOperator) EXPECT_EQ(0, persons["john"]); } -//TEST(MapTest, Map) -//{ -// const set numbers({4, 1, 3}); -// const auto mapped_set = numbers.map([](const int& age) { -// return child(age); -// }); -// EXPECT_EQ(3, mapped_set.size()); -// EXPECT_EQ(1, mapped_set[0].age); -// EXPECT_EQ(3, mapped_set[1].age); -// EXPECT_EQ(4, mapped_set[2].age); -//} -// -//TEST(MapTest, AllOf) -//{ -// const set numbers({1, 4, 2, 5, 8, 3}); -// EXPECT_TRUE(numbers.all_of([](const int &number) { return number < 10; })); -// EXPECT_FALSE(numbers.all_of([](const int &number) { return number > 2; })); -//} -// -//TEST(MapTest, AnyOf) -//{ -// const set numbers({1, 4, 2, 5, 8, 3}); -// EXPECT_TRUE(numbers.any_of([](const int &number) { return number < 5; })); -// EXPECT_FALSE(numbers.any_of([](const int &number) { return number > 10; })); -//} -// -//TEST(MapTest, NoneOf) -//{ -// const set numbers({1, 4, 2, 5, 8, 3}); -// EXPECT_TRUE(numbers.none_of([](const int &number) { return number > 10; })); -// EXPECT_FALSE(numbers.none_of([](const int &number) { return number < 6; })); -//} -// -//TEST(MapTest, Reduce) -//{ -// const set tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" }); -// const auto sentence = tokens.reduce(std::string(""), [](const std::string& partial, const std::string& token) { -// return partial.length() != 0 -// ? partial + " " + token -// : token; -// }); -// EXPECT_EQ("brown dog fox jumps lazy over quick the", sentence); -//} -// -//TEST(MapTest, Filter) -//{ -// set numbers({ 1, 3, -5, 2, -1, 9, -4 }); -// numbers.filter([](const int& element) { -// return element >= 1.5; -// }); -// EXPECT_EQ(set({2, 3, 9}), numbers); -//} -// -//TEST(MapTest, Filtered) -//{ -// const set numbers({ 1, 3, -5, 2, -1, 9, -4 }); -// auto filtered_numbers = numbers.filtered([](const int& element) { -// return element >= 1.5; -// }); -// EXPECT_EQ(set({2, 3, 9}), filtered_numbers); -// EXPECT_EQ(set({ 1, 3, -5, 2, -1, 9, -4 }), numbers); -//} -// -//TEST(MapTest, ZipWithFunctionalSet) -//{ -// const set ages({ 25, 45, 30, 63 }); -// const set persons({ "Jake", "Bob", "Michael", "Philipp" }); -// const auto zipped = ages.zip(persons); -// const auto expected = set>({ -// std::pair(25, "Bob"), -// std::pair(30, "Jake"), -// std::pair(45, "Michael"), -// std::pair(63, "Philipp"), -// }); -// EXPECT_EQ(expected, zipped); -//} -// -//TEST(MapTest, ZipWithFunctionalSetDifferentSizes) -//{ -// const set ages({ 25, 45, 30, 63 }); -// const set persons({ "Jake" }); -// EXPECT_DEATH(ages.zip(persons), ""); -//} -// -//TEST(MapTest, ZipWithStdSet) -//{ -// const set ages({ 25, 45, 30, 63 }); -// const std::set persons({ "Jake", "Bob", "Michael", "Philipp" }); -// const auto zipped = ages.zip(persons); -// const auto expected = set>({ -// std::pair(25, "Bob"), -// std::pair(30, "Jake"), -// std::pair(45, "Michael"), -// std::pair(63, "Philipp"), -// }); -// EXPECT_EQ(expected, zipped); -//} -// -//TEST(MapTest, ZipWithStdSetDifferentSizes) -//{ -// const set ages({ 25, 45, 30, 63 }); -// const std::set persons({ "Jake" }); -// EXPECT_DEATH(ages.zip(persons), ""); -//} -// -//TEST(MapTest, ZipWithFunctionalVector) -//{ -// const set ages({ 25, 45, 30, 63 }); -// const vector persons({ "Jake", "Bob", "Michael", "Philipp" }); -// const auto zipped = ages.zip(persons); -// const auto expected = set>({ -// std::pair(25, "Bob"), -// std::pair(30, "Jake"), -// std::pair(45, "Michael"), -// std::pair(63, "Philipp"), -// }); -// EXPECT_EQ(expected, zipped); -//} -// -//TEST(MapTest, ZipWithFunctionalVectorDifferentSizes) -//{ -// const set ages({ 25, 45, 30, 63 }); -// const vector persons({ "Jake" }); -// EXPECT_DEATH(ages.zip(persons), ""); -//} -// -//TEST(MapTest, ZipWithStdVector) -//{ -// const set ages({ 25, 45, 30, 63 }); -// const std::vector persons({ "Jake", "Bob", "Michael", "Philipp" }); -// const auto zipped = ages.zip(persons); -// const auto expected = set>({ -// std::pair(25, "Bob"), -// std::pair(30, "Jake"), -// std::pair(45, "Michael"), -// std::pair(63, "Philipp"), -// }); -// EXPECT_EQ(expected, zipped); -//} -// -//TEST(MapTest, ZipWithStdVectorDifferentSizes) -//{ -// const set ages({ 25, 45, 30, 63 }); -// const std::vector persons({ "Jake" }); -// EXPECT_DEATH(ages.zip(persons), ""); -//} -// -//TEST(MapTest, Keys) -//{ -// const set numbers({ 25, 45, 30, 63 }); -// const auto keys = numbers.keys(); -// EXPECT_EQ(vector({25, 30, 45, 63}), keys); -//} -// -//TEST(MapTest, RemoveExistingElement) -//{ -// set numbers({1, 4, 2}); -// numbers.remove(4); -// EXPECT_EQ(set({1, 2}), numbers); -//} -// -//TEST(MapTest, RemoveNonExistentElement) -//{ -// set numbers({1, 4, 2}); -// numbers.remove(18); -// EXPECT_EQ(set({1, 2, 4}), numbers); -//} -// -//TEST(MapTest, RemovingExistingElement) -//{ -// const set numbers({1, 4, 2}); -// const auto less_numbers = numbers.removing(4); -// EXPECT_EQ(set({1, 2}), less_numbers); -// EXPECT_EQ(set({1, 2, 4}), numbers); -//} -// -//TEST(MapTest, InsertNewElement) -//{ -// set numbers({1, 4, 2}); -// numbers.insert(18); -// EXPECT_EQ(set({1, 2, 4, 18}), numbers); -//} -// -//TEST(MapTest, InsertingNewElement) -//{ -// const set numbers({1, 4, 2}); -// const auto augmented_numbers = numbers.inserting(18); -// EXPECT_EQ(set({1, 2, 4, 18}), augmented_numbers); -// EXPECT_EQ(set({1, 2, 4}), numbers); -//} -// -//TEST(MapTest, InsertExistingElement) -//{ -// set numbers({1, 4, 2}); -// numbers.insert(2); -// EXPECT_EQ(set({1, 2, 4}), numbers); -//} -// -//TEST(MapTest, InsertingExistingElement) -//{ -// const set numbers({1, 4, 2}); -// const auto augmented_numbers = numbers.inserting(2); -// EXPECT_EQ(set({1, 2, 4}), augmented_numbers); -// EXPECT_EQ(set({1, 2, 4}), numbers); -//} +TEST(MapTest, MapValues) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + const auto mapped = persons.map_values([](const int& age) { + return std::to_string(age); + }); + + EXPECT_EQ(vector({"40", "32", "26"}), mapped); +} + +TEST(MapTest, MapKeys) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + const auto mapped = persons.map_keys([](const std::string& name) { + return name[0]; + }); + + EXPECT_EQ(vector({'d', 'j', 'm'}), mapped); +} + +TEST(MapTest, MapTo) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + const auto mapped = persons.map_to([](const std::pair& element) { + return std::make_pair(element.first[0], std::to_string(element.second) + " years"); + }); + + EXPECT_EQ((map({{'d', "40 years"}, {'j', "32 years"}, {'m', "26 years"}})), mapped); +} + +TEST(MapTest, AllOf) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + EXPECT_TRUE(persons.all_of([](const std::pair& element) { + return element.second > 20; + })); + EXPECT_FALSE(persons.all_of([](const std::pair& element) { + return element.second < 35; + })); +} + +TEST(MapTest, AnyOf) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + EXPECT_TRUE(persons.any_of([](const std::pair& element) { + return element.second == 40; + })); + EXPECT_FALSE(persons.any_of([](const std::pair& element) { + return element.second > 50; + })); +} + +TEST(MapTest, NoneOf) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + EXPECT_TRUE(persons.none_of([](const std::pair& element) { + return element.second < 18; + })); + EXPECT_FALSE(persons.none_of([](const std::pair& element) { + return element.second == 26; + })); +} + +TEST(MapTest, Reduce) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + const auto total_age = persons.reduce(0, [](const int& partial_sum, const std::pair& element) { + return partial_sum + element.second; + }); + EXPECT_EQ(98, total_age); +} + +TEST(MapTest, Filter) +{ + map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + persons.filter([](const std::pair& element) { + return element.second >= 32; + }); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}})), persons); +} + +TEST(MapTest, Filtered) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + const auto filtered_persons = persons.filtered([](const std::pair& element) { + return element.second >= 32; + }); + + EXPECT_EQ((map({{"david", 40}, {"jake", 32}})), filtered_persons); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}, {"mary", 26}})), persons); +} + +TEST(MapTest, ForEach) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + auto total_age = 0; + persons.for_each([&total_age](const std::pair& element) { + total_age += element.second; + }); + EXPECT_EQ(98, total_age); +} + +TEST(MapTest, Keys) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + EXPECT_EQ(vector({"david", "jake", "mary"}), persons.keys()); +} + +TEST(MapTest, Values) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + EXPECT_EQ(vector({40, 32, 26}), persons.values()); +} + +TEST(MapTest, RemoveExistingElement) +{ + map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + persons.remove("mary"); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}})), persons); +} + +TEST(MapTest, RemoveNonExistentElement) +{ + map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + persons.remove("bob"); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}, {"mary", 26}})), persons); +} + +TEST(MapTest, RemovingExistingElement) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + const auto reduced_persons = persons.removing("mary"); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}})), reduced_persons); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}, {"mary", 26}})), persons); +} + +TEST(MapTest, InsertNewElement) +{ + map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + persons.insert("anna", 28); + EXPECT_EQ((map({{"anna", 28}, {"david", 40}, {"jake", 32}, {"mary", 26}})), persons); +} + +TEST(MapTest, InsertingNewElement) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + const auto augmented_persons = persons.inserting("anna", 28); + EXPECT_EQ((map({{"anna", 28}, {"david", 40}, {"jake", 32}, {"mary", 26}})), augmented_persons); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}, {"mary", 26}})), persons); +} + +TEST(MapTest, InsertExistingElement) +{ + map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + persons.insert("jake", 999); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}, {"mary", 26}})), persons); +} + +TEST(MapTest, InsertingExistingElement) +{ + const map persons({{"jake", 32}, {"mary", 26}, {"david", 40}}); + const auto augmented_persons = persons.inserting("jake", 999); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}, {"mary", 26}})), augmented_persons); + EXPECT_EQ((map({{"david", 40}, {"jake", 32}, {"mary", 26}})), persons); +} TEST(MapTest, Clear) { @@ -294,36 +252,18 @@ TEST(MapTest, Contains) EXPECT_FALSE(persons.contains("bob")); } -//TEST(MapTest, EqualityOperator) -//{ -// const set set1(std::set({1, 2, 3})); -// const set set2(std::set({1, 2, 3, 2, 3})); -// EXPECT_TRUE(set1 == set2); -// EXPECT_FALSE(set1 != set2); -//} -// -//TEST(MapTest, InequalityOperator) -//{ -// const set set1(std::set({1, 2, 3})); -// const set set2(std::set({1, 2, 3, 4})); -// EXPECT_FALSE(set1 == set2); -// EXPECT_TRUE(set1 != set2); -//} -// -//TEST(MapTest, EqualityOperatorCustomType) -//{ -// const set set1({ -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate") -// }); -// -// const set set2({ -// person(15, "Jake"), -// person(18, "Jannet"), -// person(25, "Kate") -// }); -// -// EXPECT_TRUE(set1 == set2); -// EXPECT_FALSE(set1 != set2); -//} +TEST(MapTest, EqualityOperator) +{ + const map map1({{1, "one"}, {2, "two"}, {3, "three"}}); + const map map2({{1, "one"}, {2, "two"}, {3, "three"}}); + EXPECT_TRUE(map1 == map2); + EXPECT_FALSE(map1 != map2); +} + +TEST(MapTest, InequalityOperator) +{ + const map map1({{1, "one"}, {2, "two"}, {3, "three"}}); + const map map2({{1, "one"}, {2, "two"}, {4, "four"}}); + EXPECT_FALSE(map1 == map2); + EXPECT_TRUE(map1 != map2); +} diff --git a/tests/optional_test.cc b/tests/optional_test.cc index e9a4f6f..1ccf19b 100644 --- a/tests/optional_test.cc +++ b/tests/optional_test.cc @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/tests/set_test.cc b/tests/set_test.cc index 3e84090..48fe52e 100644 --- a/tests/set_test.cc +++ b/tests/set_test.cc @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/tests/test_types.h b/tests/test_types.h index 208a4f0..3205945 100644 --- a/tests/test_types.h +++ b/tests/test_types.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2022 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/tests/vector_test.cc b/tests/vector_test.cc index f4121e3..048cfe7 100644 --- a/tests/vector_test.cc +++ b/tests/vector_test.cc @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2023 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/tests/warnings.h b/tests/warnings.h index 85046f9..bbf7de9 100644 --- a/tests/warnings.h +++ b/tests/warnings.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2022 Ioannis Kaliakatsos +// Copyright (c) 2026 Ioannis Kaliakatsos // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal From 73f7901b65174a8f529e614e31a39a3d77d22f55 Mon Sep 17 00:00:00 2001 From: jkalias Date: Sun, 19 Apr 2026 14:32:05 +0200 Subject: [PATCH 09/11] Update cmake.yml --- .github/workflows/cmake.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 3f4d35c..f010a2e 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -112,6 +112,7 @@ jobs: -S . \ -B build \ -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -G "${{ matrix.config.generators }}" - name: Configure C++17 @@ -123,6 +124,7 @@ jobs: -S . \ -B build \ -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_CXX_STANDARD=17 \ -G "${{ matrix.config.generators }}" From 88c8381b306e5e6018bc5cd0cd300bb22cf54335 Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 19 Apr 2026 15:28:55 +0200 Subject: [PATCH 10/11] fixed strict comparator crash --- include/vector.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/vector.h b/include/vector.h index 3bad6d5..14e663a 100644 --- a/include/vector.h +++ b/include/vector.h @@ -577,7 +577,7 @@ class vector } #endif - // Sorts the vector in place in ascending order, when its elements support comparison by std::less_equal [<=] (mutating). + // Sorts the vector in place in ascending order, when its elements support comparison by std::less [<] (mutating). // // example: // fcpp::vector numbers({3, 1, 9, -4}); @@ -587,7 +587,7 @@ class vector // numbers -> fcpp::vector({-4, 1, 3, 9}); vector& sort_ascending() { - return sort(std::less_equal()); + return sort(std::less()); } #ifdef PARALLEL_ALGORITHM_AVAILABLE @@ -595,11 +595,11 @@ class vector // See also the sequential version for more documentation. vector& sort_ascending_parallel() { - return sort_parallel(std::less_equal()); + return sort_parallel(std::less()); } #endif - // Sorts the vector in place in descending order, when its elements support comparison by std::greater_equal [>=] (mutating). + // Sorts the vector in place in descending order, when its elements support comparison by std::greater [>] (mutating). // // example: // fcpp::vector numbers({3, 1, 9, -4}); @@ -609,7 +609,7 @@ class vector // numbers -> fcpp::vector({9, 3, 1, -4}); vector& sort_descending() { - return sort(std::greater_equal()); + return sort(std::greater()); } #ifdef PARALLEL_ALGORITHM_AVAILABLE @@ -617,7 +617,7 @@ class vector // See also the sequential version for more documentation. vector& sort_descending_parallel() { - return sort_parallel(std::greater_equal()); + return sort_parallel(std::greater()); } #endif @@ -671,7 +671,7 @@ class vector } #endif - // Sorts its elements copied and sorted in ascending order, when its elements support comparison by std::less_equal [<=] (non-mutating). + // Sorts its elements copied and sorted in ascending order, when its elements support comparison by std::less [<] (non-mutating). // // example: // const fcpp::vector numbers({3, 1, 9, -4}); @@ -681,7 +681,7 @@ class vector // sorted_numbers -> fcpp::vector({-4, 1, 3, 9}); [[nodiscard]] vector sorted_ascending() const { - return sorted(std::less_equal()); + return sorted(std::less()); } #ifdef PARALLEL_ALGORITHM_AVAILABLE @@ -689,11 +689,11 @@ class vector // See also the sequential version for more documentation. [[nodiscard]] vector sorted_ascending_parallel() const { - return sorted_parallel(std::less_equal()); + return sorted_parallel(std::less()); } #endif - // Sorts its elements copied and sorted in descending order, when its elements support comparison by std::greater_equal [>=] (non-mutating). + // Sorts its elements copied and sorted in descending order, when its elements support comparison by std::greater [>] (non-mutating). // // example: // const fcpp::vector numbers({3, 1, 9, -4}); @@ -703,7 +703,7 @@ class vector // sorted_numbers -> fcpp::vector({9, 3, 1, -4}); [[nodiscard]] vector sorted_descending() const { - return sorted(std::greater_equal()); + return sorted(std::greater()); } #ifdef PARALLEL_ALGORITHM_AVAILABLE @@ -711,7 +711,7 @@ class vector // See also the sequential version for more documentation. [[nodiscard]] vector sorted_descending_parallel() const { - return sorted_parallel(std::greater_equal()); + return sorted_parallel(std::greater()); } #endif From 93bc7191b3bc6383910f4402cac7bdc9d834fba2 Mon Sep 17 00:00:00 2001 From: jkaliak Date: Sun, 19 Apr 2026 16:06:26 +0200 Subject: [PATCH 11/11] Revert "Merge branch 'main' into functional_map" This reverts commit 223b54c064574afd7f0dfbfe65db4057b407320f, reversing changes made to 88c8381b306e5e6018bc5cd0cd300bb22cf54335. --- .github/workflows/cmake.yml | 2 +- .gitignore | 4 +- include/export_def.h | 12 +- include/index_range.h | 110 +- include/optional.h | 145 +- include/set.h | 608 ++++---- include/vector.h | 2929 +++++++++++++++++------------------ src/index_range.cc | 26 +- tests/index_range_test.cc | 159 +- tests/optional_test.cc | 90 +- tests/set_test.cc | 601 ++++--- tests/vector_test.cc | 1528 +++++++++--------- 12 files changed, 3056 insertions(+), 3158 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 3a9a05c..f010a2e 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -73,7 +73,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v2 - name: Print env run: | diff --git a/.gitignore b/.gitignore index aee6f61..e40f241 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,7 @@ compile_commands.json CTestTestfile.cmake _deps build/ -build*/ +build_cpp11/ +build_cpp17/ +build_gcc/ /.vs diff --git a/include/export_def.h b/include/export_def.h index 0e440e7..dcca3a3 100644 --- a/include/export_def.h +++ b/include/export_def.h @@ -23,13 +23,13 @@ #pragma once #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) -#ifdef FUNCTIONAL_CPP_EXPORTS -#define FunctionalCppExport __declspec( dllexport ) + #ifdef FUNCTIONAL_CPP_EXPORTS + #define FunctionalCppExport __declspec( dllexport ) + #else + #define FunctionalCppExport __declspec( dllimport ) + #endif #else -#define FunctionalCppExport __declspec( dllimport ) -#endif -#else -#define FunctionalCppExport __attribute__ ((__visibility__("default"))) + #define FunctionalCppExport __attribute__ ((__visibility__("default"))) #endif #include "compatibility.h" diff --git a/include/index_range.h b/include/index_range.h index 87625b6..6670939 100644 --- a/include/index_range.h +++ b/include/index_range.h @@ -26,60 +26,60 @@ // A struct used for container safe access based on index struct FunctionalCppExport index_range { - // Used for returning values of invalid operations - static index_range invalid; - - // Create with start index and element count (end index is calculated) - static index_range start_count(int start, int count); - - // Create with start and end index (count is calculated) - static index_range start_end(int start, int end); - - // The start index of the index range - // example: - // [0] [1] [2] [3] [4] [5] [6] - // 5 3 9 1 8 3 2 - // ^ ^ - // | | - // start end - // - // start = 2 - // end = 4 - // count = 3 - int start; - - // The end index of the index range - // example: - // [0] [1] [2] [3] [4] [5] [6] - // 5 3 9 1 8 3 2 - // ^ ^ - // | | - // start end - // - // start = 2 - // end = 4 - // count = 3 - int end; - - // The total count of the elements in the index range - // example: - // [0] [1] [2] [3] [4] [5] [6] - // 5 3 9 1 8 3 2 - // ^ ^ - // | | - // start end - // - // start = 2 - // end = 4 - // count = 3 - int count; - - // Returns true if it's safe to use its contents - bool is_valid; - - bool operator ==(const index_range& rhs) const; - bool operator !=(const index_range& rhs) const; - + // Used for returning values of invalid operations + static index_range invalid; + + // Create with start index and element count (end index is calculated) + static index_range start_count(int start, int count); + + // Create with start and end index (count is calculated) + static index_range start_end(int start, int end); + + // The start index of the index range + // example: + // [0] [1] [2] [3] [4] [5] [6] + // 5 3 9 1 8 3 2 + // ^ ^ + // | | + // start end + // + // start = 2 + // end = 4 + // count = 3 + int start; + + // The end index of the index range + // example: + // [0] [1] [2] [3] [4] [5] [6] + // 5 3 9 1 8 3 2 + // ^ ^ + // | | + // start end + // + // start = 2 + // end = 4 + // count = 3 + int end; + + // The total count of the elements in the index range + // example: + // [0] [1] [2] [3] [4] [5] [6] + // 5 3 9 1 8 3 2 + // ^ ^ + // | | + // start end + // + // start = 2 + // end = 4 + // count = 3 + int count; + + // Returns true if it's safe to use its contents + bool is_valid; + + bool operator == (const index_range& rhs) const; + bool operator != (const index_range& rhs) const; + private: - index_range(int start, int count); + index_range(int start, int count); }; diff --git a/include/optional.h b/include/optional.h index 5614253..cb051d0 100644 --- a/include/optional.h +++ b/include/optional.h @@ -25,6 +25,7 @@ #include "compatibility.h" namespace fcpp { + #ifdef CPP17_AVAILABLE #include template @@ -33,87 +34,71 @@ using optional_t = std::optional; #include #include - // A replacement for std::optional when C++17 is not available - template - class optional - { - public: - optional() - : _value{nullptr} - { - } - - ~optional() - { - reset(); - } - - optional& operator=(optional const& other) - { - _value = nullptr; - if (other.has_value()) { - _value = new T{other.value()}; - } - return *this; - } - - optional(const optional& other) - { - _value = nullptr; - if (other.has_value()) { - _value = new T{other.value()}; - } - } - - optional(T const& val) - : _value(new T{val}) - { - } - - bool has_value() const - { - return _value != nullptr; - } - - T* operator->() const - { - assert(has_value()); - return _value; - } - - T& operator*() const - { - assert(has_value()); - return *_value; - } - - const T& value() const - { - assert(has_value()); - return *_value; - } - - optional& operator=(T const& value) - { - reset(); - _value = new T(value); - return *this; - } - - private: - void reset() - { - if (_value) { - delete _value; - _value = nullptr; - } - } - - T* _value; - }; +// A replacement for std::optional when C++17 is not available +template +class optional { +public: + optional() + : _value{nullptr} + { + } + + ~optional() + { + reset(); + } + + optional(T const& val) + : _value(new T{val}) + { + } + + bool has_value() const + { + return _value != nullptr; + } + + T* operator->() const + { + assert(has_value()); + return _value; + } + + T& operator*() const + { + assert(has_value()); + return *_value; + } + + const T& value() const + { + assert(has_value()); + return *_value; + } + + optional& operator= (T const& value) + { + reset(); + _value = new T(value); + return *this; + } + +private: + void reset() + { + if (_value) + { + delete _value; + _value = nullptr; + } + } + + T* _value; +}; - template - using optional_t = optional; +template +using optional_t = optional; #endif + } diff --git a/include/set.h b/include/set.h index 800a43b..c414d54 100644 --- a/include/set.h +++ b/include/set.h @@ -26,23 +26,9 @@ #include "optional.h" namespace fcpp { - template - class vector; - // A lightweight wrapper around std::set, enabling fluent and functional - // programming on the set itself, rather than using the more procedural style - // of the standard library algorithms. - // - // Member functions can be mutating (eg. my_set.insert()) or - // non-mutating (eg. my_vector.inserting()) enforcing thread safety if needed - template > - class set - { - public: - set() - : m_set() - { - } +template +class vector; // A lightweight wrapper around std::set, enabling fluent and functional // programming on the set itself, rather than using the more procedural style @@ -213,90 +199,89 @@ class set // output_set.insert(std::to_string(key)); // } #ifdef CPP17_AVAILABLE - template , typename Transform, typename = std::enable_if_t< - std::is_invocable_r_v>> + template , typename Transform, typename = std::enable_if_t>> #else - template , typename Transform> + template , typename Transform> #endif - set map(Transform&& transform) const - { - std::set transformed_set; - for (const auto& key : m_set) { - transformed_set.insert(transform(key)); - } - return set(transformed_set); - } - - // Returns true if all keys match the predicate (return true) - // - // example: - // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); - // - // // returns true - // numbers.all_of([](const int &number) { - // return number < 10; - // }); - // - // // returns false - // numbers.all_of([](const int &number) { - // return number > 2; - // }); + set map(Transform && transform) const + { + std::set transformed_set; + for (const auto& key: m_set) { + transformed_set.insert(transform(key)); + } + return set(transformed_set); + } + + // Returns true if all keys match the predicate (return true) + // + // example: + // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); + // + // // returns true + // numbers.all_of([](const int &number) { + // return number < 10; + // }); + // + // // returns false + // numbers.all_of([](const int &number) { + // return number > 2; + // }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - bool all_of(Callable&& unary_predicate) const - { - return std::all_of(begin(), - end(), - std::forward(unary_predicate)); - } - - // Returns true if at least one key match the predicate (returns true) - // - // example: - // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); - // - // // returns true - // numbers.any_of([](const int &number) { - // return number < 5; - // }); - // - // // returns false - // numbers.any_of([](const int &number) { - // return number > 10; - // }); + bool all_of(Callable && unary_predicate) const + { + return std::all_of(begin(), + end(), + std::forward(unary_predicate)); + } + + // Returns true if at least one key match the predicate (returns true) + // + // example: + // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); + // + // // returns true + // numbers.any_of([](const int &number) { + // return number < 5; + // }); + // + // // returns false + // numbers.any_of([](const int &number) { + // return number > 10; + // }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - bool any_of(Callable&& unary_predicate) const - { - return std::any_of(begin(), - end(), - std::forward(unary_predicate)); - } - - // Returns true if none of the keys match the predicate (all return false) - // - // example: - // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); - // - // // returns true - // numbers.none_of([](const int &number) { - // return number > 10; - // }); - // - // // returns false - // numbers.none_of([](const int &number) { - // return number < 6; - // }); + bool any_of(Callable && unary_predicate) const + { + return std::any_of(begin(), + end(), + std::forward(unary_predicate)); + } + + // Returns true if none of the keys match the predicate (all return false) + // + // example: + // const fcpp::set numbers({1, 4, 2, 5, 8, 3}); + // + // // returns true + // numbers.none_of([](const int &number) { + // return number > 10; + // }); + // + // // returns false + // numbers.none_of([](const int &number) { + // return number < 6; + // }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif bool none_of(Callable && unary_predicate) const { @@ -320,158 +305,158 @@ class set // // sentence -> std::string("brown dog fox jumps lazy over quick the"); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - U reduce(const U& initial, Reduce&& reduction) const - { - auto result = initial; - for (const auto& x : m_set) { - result = reduction(result, x); - } - return result; - } + U reduce(const U& initial, Reduce&& reduction) const + { + auto result = initial; + for (const auto& x : m_set) + { + result = reduction(result, x); + } + return result; + } - // Performs the functional `filter` algorithm, in which all keys of this instance - // which match the given predicate are kept (mutating) - // - // example: - // fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); - // numbers.filter([](const int& element) { - // return element >= 1.5; - // }); - // - // outcome: - // numbers -> fcpp::set({ 2, 3, 9 }); - // - // is equivalent to: - // fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); - // for (auto i = 0; i < numbers.size(); ++i) { - // if (numbers[i] >= 1.5) { - // continue; - // } - // numbers.remove(i); - // i--; - // } + // Performs the functional `filter` algorithm, in which all keys of this instance + // which match the given predicate are kept (mutating) + // + // example: + // fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // numbers.filter([](const int& element) { + // return element >= 1.5; + // }); + // + // outcome: + // numbers -> fcpp::set({ 2, 3, 9 }); + // + // is equivalent to: + // fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // for (auto i = 0; i < numbers.size(); ++i) { + // if (numbers[i] >= 1.5) { + // continue; + // } + // numbers.remove(i); + // i--; + // } #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - set& filter(Filter&& predicate_to_keep) - { - std::set copy; - auto it = begin(); - for (; it != end(); ++it) { - if (predicate_to_keep(*it)) { - copy.insert(*it); - } - } - m_set = std::move(copy); - return *this; - } - - // Performs the functional `filter` algorithm in a copy of this instance, in which all keys - // of the copy which match the given predicate are kept (non-mutating) - // - // example: - // const fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); - // auto filtered_numbers = numbers.filtered([](const int& element) { - // return element >= 1.5; - // }); - // - // outcome: - // filtered_numbers -> fcpp::set({ 2, 3, 9 }); - // numbers -> fcpp::set({ 1, 3, -5, 2, -1, 9, -4 }); + set& filter(Filter && predicate_to_keep) + { + std::set copy; + auto it = begin(); + for (; it != end(); it++) { + if (predicate_to_keep(*it)) { + copy.insert(*it); + } + } + m_set = std::move(copy); + return *this; + } + + // Performs the functional `filter` algorithm in a copy of this instance, in which all keys + // of the copy which match the given predicate are kept (non-mutating) + // + // example: + // const fcpp::set numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // auto filtered_numbers = numbers.filtered([](const int& element) { + // return element >= 1.5; + // }); + // + // outcome: + // filtered_numbers -> fcpp::set({ 2, 3, 9 }); + // numbers -> fcpp::set({ 1, 3, -5, 2, -1, 9, -4 }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - set filtered(Filter&& predicate_to_keep) const - { - std::set copy; - auto it = begin(); - for (; it != end(); ++it) { - if (predicate_to_keep(*it)) { - copy.insert(*it); - } - } - return set(copy); - } - + set filtered(Filter && predicate_to_keep) const + { + std::set copy; + auto it = begin(); + for (; it != end(); it++) { + if (predicate_to_keep(*it)) { + copy.insert(*it); + } + } + return set(copy); + } + #ifdef CPP17_AVAILABLE - template - using deref_type = typename std::iterator_traits::value_type; - - template - struct is_valid_iterator - { - static bool const value = std::is_constructible_v>; - }; + template + using deref_type = typename std::iterator_traits::value_type; + + template + struct is_valid_iterator { + static bool const value = std::is_constructible_v>; + }; #endif - - // Performs the functional `zip` algorithm, in which every key of the resulting set is a - // tuple of this instance's key (first) and the second set's key (second). - // The sizes of the two sets must be equal. - // - // example: - // const fcpp::set ages({ 25, 45, 30, 63 }); - // const fcpp::set persons({ "Jake", "Bob", "Michael", "Philipp" }); - // const auto zipped = ages.zip(persons); - // - // outcome: - // zipped -> fcpp::set>({ - // std::pair(25, "Bob"), - // std::pair(30, "Jake"), - // std::pair(45, "Michael"), - // std::pair(63, "Philipp"), - // }) - template - [[nodiscard]] set> zip(const set& set) const - { + + // Performs the functional `zip` algorithm, in which every key of the resulting set is a + // tuple of this instance's key (first) and the second set's key (second). + // The sizes of the two sets must be equal. + // + // example: + // const fcpp::set ages({ 25, 45, 30, 63 }); + // const fcpp::set persons({ "Jake", "Bob", "Michael", "Philipp" }); + // const auto zipped = ages.zip(persons); + // + // outcome: + // zipped -> fcpp::set>({ + // std::pair(25, "Bob"), + // std::pair(30, "Jake"), + // std::pair(45, "Michael"), + // std::pair(63, "Philipp"), + // }) + template + [[nodiscard]] set> zip(const set& set) const + { #ifdef CPP17_AVAILABLE - return zip_impl(set.begin(), set.end()); + return zip_impl(set.begin(), set.end()); #else - return zip_impl(set.begin(), set.end()); + return zip_impl(set.begin(), set.end()); #endif - } - - // Performs the functional `zip` algorithm. - // The number of keys must match the set's size. - // For more details, see the zip function which accepts a fcpp::set as input. - template - [[nodiscard]] set> zip(const std::set& set) const - { - return zip(fcpp::set(set)); - } - - // Performs the functional `zip` algorithm by using the unique values of the vector. - // The number of uniques vector values must match the set's size. - // For more details, see the zip function which accepts a fcpp::set as input. - template - [[nodiscard]] set> zip(const vector& vector) const - { - const auto distinct_values = vector.distinct(); - return zip(distinct_values); - } - - // Performs the functional `zip` algorithm by using the unique values of the vector. - // The number of uniques vector values must match the set's size. - // For more details, see the zip function which accepts a fcpp::set as input. - template - [[nodiscard]] set> zip(const std::vector& vector) const - { - return zip(fcpp::vector(vector)); - } - - // Executes the given operation for each key of the set. - // The operation must not change the set's contents during execution. + } + + // Performs the functional `zip` algorithm. + // The number of keys must match the set's size. + // For more details, see the zip function which accepts a fcpp::set as input. + template + [[nodiscard]] set> zip(const std::set& set) const + { + return zip(fcpp::set(set)); + } + + // Performs the functional `zip` algorithm by using the unique values of the vector. + // The number of uniques vector values must match the set's size. + // For more details, see the zip function which accepts a fcpp::set as input. + template + [[nodiscard]] set> zip(const vector& vector) const + { + const auto distinct_values = vector.distinct(); + return zip(distinct_values); + } + + // Performs the functional `zip` algorithm by using the unique values of the vector. + // The number of uniques vector values must match the set's size. + // For more details, see the zip function which accepts a fcpp::set as input. + template + [[nodiscard]] set> zip(const std::vector& vector) const + { + return zip(fcpp::vector(vector)); + } + + // Executes the given operation for each key of the set. + // The operation must not change the set's contents during execution. #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif const set& for_each(Callable && operation) const { @@ -642,100 +627,101 @@ class set { assert_smaller_size(index); #ifdef CPP17_AVAILABLE - auto it = std::advance(begin(), index); - return *it; + auto it = std::advance(begin(), index); + return *it; #else - auto count = 0; - auto it = begin(); - while (count++ < index) { - ++it; - } - return *it; + auto count = 0; + auto it = begin(); + while (count++ < index) { + it++; + } + return *it; #endif - } - - // Returns the given key in the current constant set, allowing subscripting. - // Bounds checking (assert) is enabled for debug builds. - // Performance is O(n), so be careful for performance critical code sections. - TKey operator[](size_t index) const - { - assert_smaller_size(index); + } + + // Returns the given key in the current constant set, allowing subscripting. + // Bounds checking (assert) is enabled for debug builds. + // Performance is O(n), so be careful for performance critical code sections. + TKey operator[](size_t index) const + { + assert_smaller_size(index); #ifdef CPP17_AVAILABLE - auto it = begin(); - std::advance(it, index); - return *it; + auto it = begin(); + std::advance(it, index); + return *it; #else - auto count = 0; - auto it = begin(); - while (count++ < index) { - ++it; - } - return *it; + auto count = 0; + auto it = begin(); + while (count++ < index) { + it++; + } + return *it; #endif - } - - // Returns true if both instances have equal sizes and the corresponding elements (keys) are equal - bool operator ==(const set& rhs) const - { + } + + // Returns true if both instances have equal sizes and the corresponding elements (keys) are equal + bool operator ==(const set& rhs) const + { #ifdef CPP17_AVAILABLE - return std::equal(begin(), - end(), - rhs.begin(), - rhs.end()); + return std::equal(begin(), + end(), + rhs.begin(), + rhs.end()); #else - if (size() != rhs.size()) { - return false; - } - - auto it1 = begin(); - auto it2 = rhs.begin(); - while (it1 != end() && it2 != rhs.end()) { - if (!(*it1 == *it2)) { - return false; - } - ++it1; - ++it2; - } - - return true; + if (size() != rhs.size()) { + return false; + } + + auto it1 = begin(); + auto it2 = rhs.begin(); + while (it1 != end() && it2 != rhs.end()) { + if (!(*it1 == *it2)) { + return false; + } + it1++; + it2++; + } + + return true; #endif - } - - // Returns false if either the sizes are not equal or at least one corresponding element (key) is not equal - bool operator !=(const set& rhs) const - { - return !((*this) == rhs); - } - - private: - std::set m_set; - - void assert_smaller_size(const size_t index) const - { - assert(index < size()); - } - + } + + // Returns false if either the sizes are not equal or at least one corresponding element (key) is not equal + bool operator !=(const set& rhs) const + { + return !((*this) == rhs); + } + +private: + std::set m_set; + + void assert_smaller_size(const size_t index) const + { + assert(index < size()); + } + #ifdef CPP17_AVAILABLE - template ::value>> - [[nodiscard]] auto zip_impl(const Iterator& set_begin, const Iterator& set_end) const -> - set>> - { - using UKey = deref_type; + template::value>> + [[nodiscard]] auto zip_impl( const Iterator& set_begin, const Iterator& set_end) const -> + set>> + { + using UKey = deref_type; #else - template - [[nodiscard]] set> zip_impl(const typename std::set::const_iterator& set_begin, - const typename std::set::const_iterator& set_end) const - { + template + [[nodiscard]] set> zip_impl(const typename std::set::const_iterator& set_begin, + const typename std::set::const_iterator& set_end) const + { #endif - const auto vec_size = std::distance(set_begin, set_end); - assert(size() == vec_size); - std::set> combined_set; - auto it1 = begin(); - auto it2 = set_begin; - for (; it1 != end() && it2 != set_end; ++it1, ++it2) { - combined_set.insert({*it1, *it2}); - } - return set>(combined_set); - } - }; + const auto vec_size = std::distance(set_begin, set_end); + assert(size() == vec_size); + std::set> combined_set; + auto it1 = begin(); + auto it2 = set_begin; + for (; it1 != end() && it2 != set_end; it1++, it2++) { + combined_set.insert({*it1, *it2}); + } + return set>(combined_set); + } +}; + } diff --git a/include/vector.h b/include/vector.h index 93d6658..14e663a 100644 --- a/include/vector.h +++ b/include/vector.h @@ -22,10 +22,8 @@ #pragma once #include -#include #include #include -#include #include "index_range.h" #include "optional.h" #ifdef PARALLEL_ALGORITHM_AVAILABLE @@ -33,346 +31,348 @@ #endif namespace fcpp { - template - class set; - // A lightweight wrapper around std::vector, enabling fluent and functional - // programming on the vector itself, rather than using the more procedural style - // of the standard library algorithms. - // - // Member functions can be mutating (eg. my_vector.reverse()) or - // non-mutating (eg. my_vector.reversed()) enforcing thread safety if needed - template - class vector - { - public: - vector() - : m_vector() - { - } +template +class set; - explicit vector(const std::vector& vector) - : m_vector(vector) - { - } - - explicit vector(std::vector&& vector) - : m_vector(std::move(vector)) - { - } - - explicit vector(std::initializer_list list) - : m_vector(std::move(list)) - { - } - - // Creates a new vector by repeating a given element. - // - // example: - // const fcpp::vector filled_vector(3, "John"); - // - // outcome: - // filled_vector -> fcpp::vector({ "John", "John", "John" }) - explicit vector(size_t count, const T& element) - : m_vector(count, element) - { - } - - // Performs the functional `map` algorithm, in which every element of the resulting vector is the - // output of applying the transform function on every element of this instance. - // - // example: - // const fcpp::vector input_vector({ 1, 3, -5 }); - // const auto output_vector = input_vector.map([](const auto& element) { - // return std::to_string(element); - // }); - // - // outcome: - // output_vector -> fcpp::vector({ "1", "3", "-5" }) - // - // is equivalent to: - // const fcpp::vector input_vector({ 1, 3, -5 }); - // fcpp::vector output_vector; - // for (auto i = 0; i < input_vector.size(); ++i) { - // output_vector.insert_back(std::to_string(input_vector[i])); - // } +// A lightweight wrapper around std::vector, enabling fluent and functional +// programming on the vector itself, rather than using the more procedural style +// of the standard library algorithms. +// +// Member functions can be mutating (eg. my_vector.reverse()) or +// non-mutating (eg. my_vector.reversed()) enforcing thread safety if needed +template +class vector +{ +public: + vector() + : m_vector() + { + } + + explicit vector(const std::vector& vector) + : m_vector(vector) + { + } + + explicit vector(std::vector&& vector) + : m_vector(std::move(vector)) + { + } + + explicit vector(std::initializer_list list) + : m_vector(std::move(list)) + { + } + + // Creates a new vector by repeating a given element. + // + // example: + // const fcpp::vector filled_vector(3, "John"); + // + // outcome: + // filled_vector -> fcpp::vector({ "John", "John", "John" }) + explicit vector(size_t count, const T& element) + : m_vector(count, element) + { + } + + // Performs the functional `map` algorithm, in which every element of the resulting vector is the + // output of applying the transform function on every element of this instance. + // + // example: + // const fcpp::vector input_vector({ 1, 3, -5 }); + // const auto output_vector = input_vector.map([](const auto& element) { + // return std::to_string(element); + // }); + // + // outcome: + // output_vector -> fcpp::vector({ "1", "3", "-5" }) + // + // is equivalent to: + // const fcpp::vector input_vector({ 1, 3, -5 }); + // fcpp::vector output_vector; + // for (auto i = 0; i < input_vector.size(); ++i) { + // output_vector.insert_back(std::to_string(input_vector[i])); + // } #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - vector map(Transform&& transform) const - { - std::vector transformed_vector; - transformed_vector.reserve(m_vector.size()); - std::transform(m_vector.begin(), - m_vector.end(), - std::back_inserter(transformed_vector), - std::forward(transform)); - return vector(transformed_vector); - } - + vector map(Transform && transform) const + { + std::vector transformed_vector; + transformed_vector.reserve(m_vector.size()); + std::transform(m_vector.begin(), + m_vector.end(), + std::back_inserter(transformed_vector), + std::forward(transform)); + return vector(transformed_vector); + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Performs the functional `map` algorithm in parallel. - // See also the sequential version for more documentation. - template >> - vector map_parallel(Transform&& transform) const - { - std::vector transformed_vector; - transformed_vector.resize(m_vector.size()); - std::transform(std::execution::par, - m_vector.cbegin(), - m_vector.cend(), - transformed_vector.begin(), - std::forward(transform)); - return vector(transformed_vector); - } + // Performs the functional `map` algorithm in parallel. + // See also the sequential version for more documentation. + template >> + vector map_parallel(Transform && transform) const + { + std::vector transformed_vector; + transformed_vector.resize(m_vector.size()); + std::transform(std::execution::par, + m_vector.cbegin(), + m_vector.cend(), + transformed_vector.begin(), + std::forward(transform)); + return vector(transformed_vector); + } #endif - - // Returns true if all elements match the predicate (return true) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // - // // returns true - // numbers.all_of([](const auto &number) { - // return number < 10; - // }); - // - // // returns false - // numbers.all_of([](const auto &number) { - // return number > 2; - // }); + + // Returns true if all elements match the predicate (return true) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // + // // returns true + // numbers.all_of([](const auto &number) { + // return number < 10; + // }); + // + // // returns false + // numbers.all_of([](const auto &number) { + // return number > 2; + // }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - bool all_of(Callable&& unary_predicate) const - { - return std::all_of(begin(), - end(), - std::forward(unary_predicate)); - } - + bool all_of(Callable && unary_predicate) const + { + return std::all_of(begin(), + end(), + std::forward(unary_predicate)); + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Performs the `all_of` algorithm in parallel. - // See also the sequential version for more documentation. - template >> - bool all_of_parallel(Callable&& unary_predicate) const - { - return std::all_of(std::execution::par, - begin(), - end(), - std::forward(unary_predicate)); - } + // Performs the `all_of` algorithm in parallel. + // See also the sequential version for more documentation. + template >> + bool all_of_parallel(Callable && unary_predicate) const + { + return std::all_of(std::execution::par, + begin(), + end(), + std::forward(unary_predicate)); + } #endif - - // Returns true if at least one of the elements matches the predicate (returns true) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // - // // returns true - // numbers.any_of([](const auto &number) { - // return number < 5; - // }); - // - // // returns false - // numbers.any_of([](const auto &number) { - // return number > 9; - // }); + + // Returns true if at least one of the elements matches the predicate (returns true) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // + // // returns true + // numbers.any_of([](const auto &number) { + // return number < 5; + // }); + // + // // returns false + // numbers.any_of([](const auto &number) { + // return number > 9; + // }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - bool any_of(Callable&& unary_predicate) const - { - return std::any_of(begin(), - end(), - std::forward(unary_predicate)); - } - + bool any_of(Callable && unary_predicate) const + { + return std::any_of(begin(), + end(), + std::forward(unary_predicate)); + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Performs the `any_of` algorithm in parallel. - // See also the sequential version for more documentation. - template >> - bool any_of_parallel(Callable&& unary_predicate) const - { - return std::any_of(std::execution::par, - begin(), - end(), - std::forward(unary_predicate)); - } + // Performs the `any_of` algorithm in parallel. + // See also the sequential version for more documentation. + template >> + bool any_of_parallel(Callable && unary_predicate) const + { + return std::any_of(std::execution::par, + begin(), + end(), + std::forward(unary_predicate)); + } #endif - - // Returns true if no element matches the predicate (all return false) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // - // // returns true - // numbers.none_of([](const auto &number) { - // return number < -2; - // }); - // - // // returns false - // numbers.none_of([](const auto &number) { - // return number > 7; - // }); + + // Returns true if no element matches the predicate (all return false) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // + // // returns true + // numbers.none_of([](const auto &number) { + // return number < -2; + // }); + // + // // returns false + // numbers.none_of([](const auto &number) { + // return number > 7; + // }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - bool none_of(Callable&& unary_predicate) const - { - return std::none_of(begin(), - end(), - std::forward(unary_predicate)); - } - + bool none_of(Callable && unary_predicate) const + { + return std::none_of(begin(), + end(), + std::forward(unary_predicate)); + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Performs the `none_of` algorithm in parallel. - // See also the sequential version for more documentation. - template >> - bool none_of_parallel(Callable&& unary_predicate) const - { - return std::none_of(std::execution::par, - begin(), - end(), - std::forward(unary_predicate)); - } + // Performs the `none_of` algorithm in parallel. + // See also the sequential version for more documentation. + template >> + bool none_of_parallel(Callable && unary_predicate) const + { + return std::none_of(std::execution::par, + begin(), + end(), + std::forward(unary_predicate)); + } #endif - // Performs the functional `reduce` (fold/accumulate) algorithm, by returning the result of - // accumulating all the values in the vector to an initial value. (non-mutating) - // - // example: - // const fcpp::vector tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" }); - // const auto sentence = tokens.reduce("", [](const std::string& partial, const std::string& token) { - // return partial.length() != 0 - // ? partial + " " + token - // : token; - // }); - // - // outcome: - // sentence -> std::string("the quick brown fox jumps over the lazy brown dog"); + // Performs the functional `reduce` (fold/accumulate) algorithm, by returning the result of + // accumulating all the values in the vector to an initial value. (non-mutating) + // + // example: + // const fcpp::vector tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" }); + // const auto sentence = tokens.reduce("", [](const std::string& partial, const std::string& token) { + // return partial.length() != 0 + // ? partial + " " + token + // : token; + // }); + // + // outcome: + // sentence -> std::string("the quick brown fox jumps over the lazy brown dog"); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - U reduce(const U& initial, Reduce&& reduction) const - { - auto result = initial; - for (const auto& x : m_vector) { - result = reduction(result, x); - } - return result; - } + U reduce(const U& initial, Reduce&& reduction) const + { + auto result = initial; + for(const auto &x: m_vector) + { + result = reduction(result, x); + } + return result; + } - // Performs the functional `filter` algorithm, in which all elements of this instance - // which match the given predicate are kept (mutating) - // - // example: - // fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); - // numbers.filter([](const auto& element) { - // return element >= 1.5; - // }); - // - // outcome: - // numbers -> fcpp::vector({ 3, 2, 9 }); - // - // is equivalent to: - // fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); - // for (auto i = 0; i < numbers.size(); ++i) { - // if (numbers[i] >= 1.5) { - // continue; - // } - // numbers.remove_at(i); - // i--; - // } + // Performs the functional `filter` algorithm, in which all elements of this instance + // which match the given predicate are kept (mutating) + // + // example: + // fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // numbers.filter([](const auto& element) { + // return element >= 1.5; + // }); + // + // outcome: + // numbers -> fcpp::vector({ 3, 2, 9 }); + // + // is equivalent to: + // fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // for (auto i = 0; i < numbers.size(); ++i) { + // if (numbers[i] >= 1.5) { + // continue; + // } + // numbers.remove_at(i); + // i--; + // } #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - vector& filter(Filter&& predicate_to_keep) - { - m_vector.erase(std::remove_if(m_vector.begin(), - m_vector.end(), - [predicate=std::forward(predicate_to_keep)](const T& element){ - return !predicate(element); - }), m_vector.end()); - return *this; - } - + vector& filter(Filter && predicate_to_keep) + { + m_vector.erase(std::remove_if(m_vector.begin(), + m_vector.end(), + [predicate=std::forward(predicate_to_keep)](const T& element) { + return !predicate(element); + }), m_vector.end()); + return *this; + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Performs the functional `filter` algorithm in parallel. - // See also the sequential version for more documentation. - template >> - vector& filter_parallel(Filter&& predicate_to_keep) - { - m_vector.erase(std::remove_if(std::execution::par, - m_vector.begin(), - m_vector.end(), - [predicate=std::forward(predicate_to_keep)](const T& element){ - return !predicate(element); - }), m_vector.end()); - return *this; - } + // Performs the functional `filter` algorithm in parallel. + // See also the sequential version for more documentation. + template >> + vector& filter_parallel(Filter && predicate_to_keep) + { + m_vector.erase(std::remove_if(std::execution::par, + m_vector.begin(), + m_vector.end(), + [predicate=std::forward(predicate_to_keep)](const T& element) { + return !predicate(element); + }), m_vector.end()); + return *this; + } #endif - - // Performs the functional `filter` algorithm in a copy of this instance, in which all elements of - // the copy which match the given predicate are kept (non-mutating) - // - // example: - // const fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); - // const auto filtered_numbers = numbers.filtered([](const auto& element) { - // return element >= 1.5; - // }); - // - // outcome: - // numbers -> fcpp::vector({ 1, 3, -5, 2, -1, 9, -4 }) - // filtered_numbers -> fcpp::vector({ 3, 2, 9 }) - // - // is equivalent to: - // const fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); - // fcpp::vector filtered_numbers; - // for (auto i = 0; i < numbers.size(); ++i) { - // if (numbers[i] >= 1.5) { - // filtered_numbers.insert_back(numbers[i]); - // } - // } + + // Performs the functional `filter` algorithm in a copy of this instance, in which all elements of + // the copy which match the given predicate are kept (non-mutating) + // + // example: + // const fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // const auto filtered_numbers = numbers.filtered([](const auto& element) { + // return element >= 1.5; + // }); + // + // outcome: + // numbers -> fcpp::vector({ 1, 3, -5, 2, -1, 9, -4 }) + // filtered_numbers -> fcpp::vector({ 3, 2, 9 }) + // + // is equivalent to: + // const fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // fcpp::vector filtered_numbers; + // for (auto i = 0; i < numbers.size(); ++i) { + // if (numbers[i] >= 1.5) { + // filtered_numbers.insert_back(numbers[i]); + // } + // } #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - vector filtered(Callable&& predicate_to_keep) const - { - std::vector filtered_vector; - filtered_vector.reserve(m_vector.size()); - std::copy_if(m_vector.begin(), - m_vector.end(), - std::back_inserter(filtered_vector), - std::forward(predicate_to_keep)); - return vector(filtered_vector); - } - + vector filtered(Callable && predicate_to_keep) const + { + std::vector filtered_vector; + filtered_vector.reserve(m_vector.size()); + std::copy_if(m_vector.begin(), + m_vector.end(), + std::back_inserter(filtered_vector), + std::forward(predicate_to_keep)); + return vector(filtered_vector); + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Performs the `filtered` algorithm in parallel. - // See also the sequential version for more documentation. - template >> - vector filtered_parallel(Callable&& predicate_to_keep) const - { + // Performs the `filtered` algorithm in parallel. + // See also the sequential version for more documentation. + template >> + vector filtered_parallel(Callable && predicate_to_keep) const + { #ifdef _MSC_VER - // Visual Studio compiler is stricter than GCC in its use of iterators, so back_inserter wouldn't work here - auto copy(*this); - copy.filter_parallel(predicate_to_keep); - return copy; + // Visual Studio compiler is stricter than GCC in its use of iterators, so back_inserter wouldn't work here + auto copy(*this); + copy.filter_parallel(predicate_to_keep); + return copy; #else std::vector filtered_vector; filtered_vector.reserve(m_vector.size()); @@ -383,199 +383,198 @@ namespace fcpp { std::forward(predicate_to_keep)); return vector(filtered_vector); #endif - } + } #endif - - // Reverses the order of the elements in place (mutating) - // - // example: - // fcpp::vector numbers_vector({ 1, 3, -5, 2, -1, 9, -4 }); - // numbers_vector.reverse(); - // - // outcome: - // numbers_vector -> fcpp::vector({ -4, 9, -1, 2, -5, 3, 1 }) - vector& reverse() - { - std::reverse(m_vector.begin(), m_vector.end()); - return *this; - } - - // Returns a copy of this instance, whose elements are in reverse order (non-mutating) - // - // example: - // const fcpp::vector input_vector({ 1, 3, -5, 2, -1, 9, -4 }); - // const auto reversed_vector = input_vector.reversed(); - // - // outcome: - // input_vector -> fcpp::vector({ 1, 3, -5, 2, -1, 9, -4 }); - // reversed_vector -> fcpp::vector({ -4, 9, -1, 2, -5, 3, 1 }) - [[nodiscard]] vector reversed() const - { - std::vector reversed_vector(m_vector.crbegin(), m_vector.crend()); - return vector(std::move(reversed_vector)); - } - + + // Reverses the order of the elements in place (mutating) + // + // example: + // fcpp::vector numbers_vector({ 1, 3, -5, 2, -1, 9, -4 }); + // numbers_vector.reverse(); + // + // outcome: + // numbers_vector -> fcpp::vector({ -4, 9, -1, 2, -5, 3, 1 }) + vector& reverse() + { + std::reverse(m_vector.begin(), m_vector.end()); + return *this; + } + + // Returns a copy of this instance, whose elements are in reverse order (non-mutating) + // + // example: + // const fcpp::vector input_vector({ 1, 3, -5, 2, -1, 9, -4 }); + // const auto reversed_vector = input_vector.reversed(); + // + // outcome: + // input_vector -> fcpp::vector({ 1, 3, -5, 2, -1, 9, -4 }); + // reversed_vector -> fcpp::vector({ -4, 9, -1, 2, -5, 3, 1 }) + [[nodiscard]] vector reversed() const + { + std::vector reversed_vector(m_vector.crbegin(), m_vector.crend()); + return vector(std::move(reversed_vector)); + } + #ifdef CPP17_AVAILABLE - template - using deref_type = typename std::iterator_traits::value_type; - - template - struct is_valid_iterator - { - static bool const value = std::is_constructible_v>; - }; + template + using deref_type = typename std::iterator_traits::value_type; + + template + struct is_valid_iterator { + static bool const value = std::is_constructible_v>; + }; #endif - - // Performs the functional `zip` algorithm, in which every element of the resulting vector is a - // tuple of this instance's element (first) and the second vector's element (second) at the same - // index. The sizes of the two vectors must be equal. - // - // example: - // const fcpp::vector ages_vector({32, 25, 53}); - // const fcpp::vector names_vector({"Jake", "Mary", "John"}); - // const auto zipped_vector = ages_vector.zip(names_vector); - // - // outcome: - // zipped_vector -> fcpp::vector>({ - // (32, "Jake"), - // (25, "Mary"), - // (53, "John"), - // }) - // - // is equivalent to: - // const fcpp::vector ages_vector({32, 25, 53}); - // const fcpp::vector names_vector({"Jake", "Mary", "John"}); - // fcpp::vector> zipped_vector; - // for (auto i = 0; i < ages_vector.size(); ++i) { - // fcpp::vector::pair tuple; - // tuple.first = ages_vector[i]; - // tuple.second = names_vector[i]; - // zipped_vector.insert_back(tuple); - // } - template - [[nodiscard]] vector> zip(const vector& vector) const - { + + // Performs the functional `zip` algorithm, in which every element of the resulting vector is a + // tuple of this instance's element (first) and the second vector's element (second) at the same + // index. The sizes of the two vectors must be equal. + // + // example: + // const fcpp::vector ages_vector({32, 25, 53}); + // const fcpp::vector names_vector({"Jake", "Mary", "John"}); + // const auto zipped_vector = ages_vector.zip(names_vector); + // + // outcome: + // zipped_vector -> fcpp::vector>({ + // (32, "Jake"), + // (25, "Mary"), + // (53, "John"), + // }) + // + // is equivalent to: + // const fcpp::vector ages_vector({32, 25, 53}); + // const fcpp::vector names_vector({"Jake", "Mary", "John"}); + // fcpp::vector> zipped_vector; + // for (auto i = 0; i < ages_vector.size(); ++i) { + // fcpp::vector::pair tuple; + // tuple.first = ages_vector[i]; + // tuple.second = names_vector[i]; + // zipped_vector.insert_back(tuple); + // } + template + [[nodiscard]] vector> zip(const vector& vector) const + { #ifdef CPP17_AVAILABLE - return zip_impl(vector.begin(), vector.end()); + return zip_impl(vector.begin(), vector.end()); #else - return zip_impl(vector.begin(), vector.end()); + return zip_impl(vector.begin(), vector.end()); #endif - } - - // Performs the functional `zip` algorithm, in which every element of the resulting vector is a - // tuple of this instance's element (first) and the second vector's element (second) at the same - // index. The sizes of the two vectors must be equal. - // - // example: - // const fcpp::vector ages_vector({32, 25, 53}); - // const std::vector names_vector({"Jake", "Mary", "John"}); - // const auto zipped_vector = ages_vector.zip(names_vector); - // - // outcome: - // zipped_vector -> fcpp::vector>({ - // (32, "Jake"), - // (25, "Mary"), - // (53, "John"), - // }) - // - // is equivalent to: - // const fcpp::vector ages_vector({32, 25, 53}); - // const std::vector names_vector({"Jake", "Mary", "John"}); - // fcpp::vector> zipped_vector; - // for (auto i = 0; i < ages_vector.size(); ++i) { - // fcpp::vector::pair tuple; - // tuple.first = ages_vector[i]; - // tuple.second = names_vector[i]; - // zipped_vector.insert_back(tuple); - // } - template - [[nodiscard]] vector> zip(const std::vector& vector) const - { + } + + // Performs the functional `zip` algorithm, in which every element of the resulting vector is a + // tuple of this instance's element (first) and the second vector's element (second) at the same + // index. The sizes of the two vectors must be equal. + // + // example: + // const fcpp::vector ages_vector({32, 25, 53}); + // const std::vector names_vector({"Jake", "Mary", "John"}); + // const auto zipped_vector = ages_vector.zip(names_vector); + // + // outcome: + // zipped_vector -> fcpp::vector>({ + // (32, "Jake"), + // (25, "Mary"), + // (53, "John"), + // }) + // + // is equivalent to: + // const fcpp::vector ages_vector({32, 25, 53}); + // const std::vector names_vector({"Jake", "Mary", "John"}); + // fcpp::vector> zipped_vector; + // for (auto i = 0; i < ages_vector.size(); ++i) { + // fcpp::vector::pair tuple; + // tuple.first = ages_vector[i]; + // tuple.second = names_vector[i]; + // zipped_vector.insert_back(tuple); + // } + template + [[nodiscard]] vector> zip(const std::vector& vector) const + { #ifdef CPP17_AVAILABLE - return zip_impl(vector.cbegin(), vector.cend()); + return zip_impl(vector.cbegin(), vector.cend()); #else - return zip_impl(vector.cbegin(), vector.cend()); + return zip_impl(vector.cbegin(), vector.cend()); #endif - } - - // example: - // const fcpp::vector ages_vector({32, 25, 53}); - // const std::initializer_list names_vector({"Jake", "Mary", "John"}); - // const auto zipped_vector = ages_vector.zip(names_vector); - // - // outcome: - // zipped_vector -> fcpp::vector>({ - // (32, "Jake"), - // (25, "Mary"), - // (53, "John"), - // }) - // - // is equivalent to: - // const fcpp::vector ages_vector({32, 25, 53}); - // const std::initializer_list names_vector({"Jake", "Mary", "John"}); - // fcpp::vector> zipped_vector; - // for (auto i = 0; i < ages_vector.size(); ++i) { - // fcpp::vector::pair tuple; - // tuple.first = ages_vector[i]; - // tuple.second = names_vector[i]; - // zipped_vector.insert_back(tuple); - // } - template - [[nodiscard]] vector> zip(const std::initializer_list& list) const - { + } + + // example: + // const fcpp::vector ages_vector({32, 25, 53}); + // const std::initializer_list names_vector({"Jake", "Mary", "John"}); + // const auto zipped_vector = ages_vector.zip(names_vector); + // + // outcome: + // zipped_vector -> fcpp::vector>({ + // (32, "Jake"), + // (25, "Mary"), + // (53, "John"), + // }) + // + // is equivalent to: + // const fcpp::vector ages_vector({32, 25, 53}); + // const std::initializer_list names_vector({"Jake", "Mary", "John"}); + // fcpp::vector> zipped_vector; + // for (auto i = 0; i < ages_vector.size(); ++i) { + // fcpp::vector::pair tuple; + // tuple.first = ages_vector[i]; + // tuple.second = names_vector[i]; + // zipped_vector.insert_back(tuple); + // } + template + [[nodiscard]] vector> zip(const std::initializer_list& list) const + { #ifdef CPP17_AVAILABLE - return zip_impl(list.begin(), list.end()); + return zip_impl(list.begin(), list.end()); #else - return zip(std::vector(list)); + return zip(std::vector(list)); #endif - } - - // Sorts the vector in place (mutating). The comparison predicate takes two elements - // `v1` and `v2` and returns true if the first element `v1` should appear before `v2`. - // - // example: - // struct person - // { - // int age; - // std::string name; - // }; - // ... - // fcpp::vector persons_vector({ - // person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") - // }); - // persons_vector.sort([](const auto& person1, const auto& person2) { - // return person1.name < person2.name; - // }); - // - // outcome: - // person_vector -> fcpp::vector({ - // person(8, "Alice"), person(34, "Bob"), person(45, "Jake"), person(52, "Manfred") - // }); + } + + // Sorts the vector in place (mutating). The comparison predicate takes two elements + // `v1` and `v2` and returns true if the first element `v1` should appear before `v2`. + // + // example: + // struct person + // { + // int age; + // std::string name; + // }; + // ... + // fcpp::vector persons_vector({ + // person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") + // }); + // persons_vector.sort([](const auto& person1, const auto& person2) { + // return person1.name < person2.name; + // }); + // + // outcome: + // person_vector -> fcpp::vector({ + // person(8, "Alice"), person(34, "Bob"), person(45, "Jake"), person(52, "Manfred") + // }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - vector& sort(Sortable&& comparison_predicate) - { - std::sort(m_vector.begin(), - m_vector.end(), - std::forward(comparison_predicate)); - return *this; - } - + vector& sort(Sortable && comparison_predicate) + { + std::sort(m_vector.begin(), + m_vector.end(), + std::forward(comparison_predicate)); + return *this; + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Performs the `sort` algorithm in parallel. - // See also the sequential version for more documentation. - template >> - vector& sort_parallel(Sortable&& comparison_predicate) - { - std::sort(std::execution::par, - m_vector.begin(), - m_vector.end(), - std::forward(comparison_predicate)); - return *this; - } + // Performs the `sort` algorithm in parallel. + // See also the sequential version for more documentation. + template >> + vector& sort_parallel(Sortable && comparison_predicate) + { + std::sort(std::execution::par, + m_vector.begin(), + m_vector.end(), + std::forward(comparison_predicate)); + return *this; + } #endif // Sorts the vector in place in ascending order, when its elements support comparison by std::less [<] (mutating). @@ -621,55 +620,55 @@ namespace fcpp { return sort_parallel(std::greater()); } #endif - - // Returns its elements copied and sorted (non-mutating). The comparison predicate takes two elements - // `v1` and `v2` and returns true if the first element `v1` should appear before `v2`. - // - // example: - // struct person - // { - // int age; - // std::string name; - // }; - // ... - // const fcpp::vector persons_vector({ - // person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") - // }); - // auto sorted_persons_vector = persons_vector.sorted([](const auto& person1, const auto& person2) { - // return person1.name < person2.name; - // }); - // - // outcome: - // sorted_persons_vector -> fcpp::vector({ - // person(8, "Alice"), person(34, "Bob"), person(45, "Jake"), person(52, "Manfred") - // }); + + // Returns its elements copied and sorted (non-mutating). The comparison predicate takes two elements + // `v1` and `v2` and returns true if the first element `v1` should appear before `v2`. + // + // example: + // struct person + // { + // int age; + // std::string name; + // }; + // ... + // const fcpp::vector persons_vector({ + // person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") + // }); + // auto sorted_persons_vector = persons_vector.sorted([](const auto& person1, const auto& person2) { + // return person1.name < person2.name; + // }); + // + // outcome: + // sorted_persons_vector -> fcpp::vector({ + // person(8, "Alice"), person(34, "Bob"), person(45, "Jake"), person(52, "Manfred") + // }); #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - vector sorted(Sortable&& comparison_predicate) const - { - auto sorted_vector(m_vector); - std::sort(sorted_vector.begin(), - sorted_vector.end(), - std::forward(comparison_predicate)); - return vector(sorted_vector); - } - + vector sorted(Sortable && comparison_predicate) const + { + auto sorted_vector(m_vector); + std::sort(sorted_vector.begin(), + sorted_vector.end(), + std::forward(comparison_predicate)); + return vector(sorted_vector); + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Performs the `sorted` algorithm in parallel. - // See also the sequential version for more documentation. - template >> - vector sorted_parallel(Sortable&& comparison_predicate) const - { - auto sorted_vector(m_vector); - std::sort(std::execution::par, - sorted_vector.begin(), - sorted_vector.end(), - std::forward(comparison_predicate)); - return fcpp::vector(sorted_vector); - } + // Performs the `sorted` algorithm in parallel. + // See also the sequential version for more documentation. + template >> + vector sorted_parallel(Sortable && comparison_predicate) const + { + auto sorted_vector(m_vector); + std::sort(std::execution::par, + sorted_vector.begin(), + sorted_vector.end(), + std::forward(comparison_predicate)); + return fcpp::vector(sorted_vector); + } #endif // Sorts its elements copied and sorted in ascending order, when its elements support comparison by std::less [<] (non-mutating). @@ -715,974 +714,974 @@ namespace fcpp { return sorted_parallel(std::greater()); } #endif - - // Executes the given operation for each element of the vector. The operation must not - // change the vector's contents during execution. + + // Executes the given operation for each element of the vector. The operation must not + // change the vector's contents during execution. #ifdef CPP17_AVAILABLE - template >> + template >> #else - template + template #endif - const vector& for_each(Callable&& operation) const - { - std::for_each(m_vector.cbegin(), - m_vector.cend(), - std::forward(operation)); - return *this; - } - + const vector& for_each(Callable && operation) const + { + std::for_each(m_vector.cbegin(), + m_vector.cend(), + std::forward(operation)); + return *this; + } + #ifdef PARALLEL_ALGORITHM_AVAILABLE - // Executes the given operation for each element of the vector in parallel. The operation must not - // change the vector's contents during execution. - template >> - const vector& for_each_parallel(Callable&& operation) const - { - std::for_each(std::execution::par, - m_vector.cbegin(), - m_vector.cend(), - std::forward(operation)); - return *this; - } -#endif - - // Returns the first index in which the given element is found in the vector. - // In case of multiple occurrences, only the first index is returned - // (see find_all_indices for multiple occurrences). - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const auto index_of_one = numbers.find_first_index(1); - // const auto index_of_nine = numbers.find_first_index(9); - // - // outcome: - // index_of_one.value() -> 0 - // index_of_one.has_value() -> true - // index_of_nine.has_value() -> false - [[nodiscard]] fcpp::optional_t find_first_index(const T& element) const - { - auto const it = std::find(m_vector.cbegin(), - m_vector.cend(), - element); - if (it != m_vector.cend()) { - auto index = std::distance(m_vector.cbegin(), it); - return index; - } - return fcpp::optional_t(); - } - - // Returns the last index in which the given element is found in the vector. - // In case of multiple occurrences, only the last index is returned - // (see find_all_indices for multiple occurrences). - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, -6, 3, 1, 7, 1}); - // const auto index_of_one = numbers.find_last_index(1); - // const auto index_of_nine = numbers.find_last_index(9); - // - // outcome: - // index_of_one.value() -> 8 - // index_of_one.has_value() -> true - // index_of_nine.has_value() -> false - [[nodiscard]] fcpp::optional_t find_last_index(const T& element) const - { - auto const it = std::find(m_vector.crbegin(), - m_vector.crend(), - element); - if (it != m_vector.crend()) { - auto index = std::distance(it, m_vector.crend()) - 1; - return index; - } - return fcpp::optional_t(); - } - - // Returns all indices in which the given element is found in the vector. - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 9, 1}); - // const auto indices_of_one = numbers.find_all_indices(1); - // const auto indices_of_ten = numbers.find_all_indices(10); - // - // outcome: - // indices_of_one -> { 0, 6, 8 } - // indices_of_ten -> empty vector - [[nodiscard]] std::vector find_all_indices(const T& element) const - { - std::vector indices; - auto it = std::find(m_vector.cbegin(), - m_vector.cend(), - element); - while (it != m_vector.cend()) { - indices.push_back(std::distance(m_vector.cbegin(), it)); - ++it; - it = std::find(it, m_vector.cend(), element); - } - return indices; - } - - // Removes the element at `index` (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.remove_at(4); - // - // outcome: - // numbers -> fcpp::vector({1, 4, 2, 5, 3, 1, 7, 1}); - vector& remove_at(size_t index) - { - assert_smaller_size(index); - m_vector.erase(begin() + index); - return *this; - } - - // Returns a copy of itself in which the element at `index` is removed (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto shorter_vector = numbers.removing_at(4); - // - // outcome: - // shorter_vector -> fcpp::vector({1, 4, 2, 5, 3, 1, 7, 1}); - [[nodiscard]] vector removing_at(size_t index) const - { - assert_smaller_size(index); - auto copy(m_vector); - copy.erase(copy.begin() + index); - return vector(copy); - } - - // Removes the last element, if present (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.remove_back(); - // - // outcome: - // numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7}); - vector& remove_back() - { - m_vector.pop_back(); - return *this; - } - - // Returns a copy of itself in which the last element is removed (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto shorter_vector = numbers.removing_back(); - // - // outcome: - // shorter_vector -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7}); - [[nodiscard]] vector removing_back() const - { - auto copy(m_vector); - copy.pop_back(); - return vector(copy); - } - - // Removes the first element, if present (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.remove_front(); - // - // outcome: - // numbers -> fcpp::vector({4, 2, 5, 8, 3, 1, 7, 1}); - vector& remove_front() - { - if (size() == 0) { - return *this; - } - return remove_at(0); - } - - // Returns a copy of itself in which the first element is removed (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto shorter_numbers = numbers.removing_front(); - // - // outcome: - // shorter_numbers -> fcpp::vector({4, 2, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] vector removing_front() const - { - if (size() == 0) { - return *this; - } - return removing_at(0); - } - - // Removes the elements whose index is contained in the given index range (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.remove_range(index_range::start_count(2, 3)); - // - // outcome: - // numbers -> fcpp::vector({ 1, 4, 2, 7, 1 }) - vector& remove_range(index_range range) - { - if (!range.is_valid || size() < range.end + 1) { - return *this; - } - m_vector.erase(begin() + range.start, - begin() + range.start + range.count); - return *this; - } - - // Returns a copy by removing the elements whose index is contained in the given index range (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const auto shorter_vector = numbers.removing_range(index_range::start_count(2, 3)); - // - // outcome: - // shorter_vector -> fcpp::vector({ 1, 4, 3, 1, 7, 1 }) - [[nodiscard]] vector removing_range(index_range range) const - { - if (!range.is_valid || size() < range.end + 1) { - return *this; - } - auto shorter_vector(m_vector); - shorter_vector.erase(shorter_vector.begin() + range.start, - shorter_vector.begin() + range.start + range.count); - return vector(shorter_vector); - } - - // Inserts an element at the given index, therefore changing the vector's contents (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.insert_at(3, 18); - // - // outcome: - // numbers -> fcpp::vector({1, 4, 2, 18, 5, 8, 3, 1, 7, 1}); - vector& insert_at(size_t index, const T& element) - { - assert_smaller_or_equal_size(index); - m_vector.insert(begin() + index, element); - return *this; - } - - // Returns a copy by inserting an element at the given index (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto augmented_numbers = numbers.inserting_at(3, 18); - // - // outcome: - // augmented_numbers -> fcpp::vector({1, 4, 2, 18, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] vector inserting_at(size_t index, const T& element) const - { - assert_smaller_or_equal_size(index); - auto copy(m_vector); - copy.insert(copy.begin() + index, element); - return vector(copy); - } - - // Inserts a range of elements starting at the given index, therefore changing the vector's contents (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const fcpp::vector vector_to_insert({9, -5, 6}); - // numbers.insert_at(3, vector_to_insert); - // - // outcome: - // numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - vector& insert_at(size_t index, const vector& vector) - { - return insert_at_impl(index, vector.begin(), vector.end()); - } - - // Returns a copy by inserting a range of elements starting at the given index (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const fcpp::vector vector_to_insert({9, -5, 6}); - // auto augmented_numbers = numbers.inserting_at(3, vector_to_insert); - // - // outcome: - // augmented_numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] vector inserting_at(size_t index, const vector& vector) const - { - return inserting_at_impl(index, vector.begin(), vector.end()); - } - - // Inserts a range of elements starting at the given index, therefore changing the vector's contents (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const std::vector vector_to_insert({9, -5, 6}); - // numbers.insert_at(3, vector_to_insert); - // - // outcome: - // numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - vector& insert_at(size_t index, const std::vector& vector) - { - return insert_at_impl(index, vector.cbegin(), vector.cend()); - } - - // Returns a copy by inserting a range of elements starting at the given index (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const std::vector vector_to_insert({9, -5, 6}); - // auto augmented_numbers = numbers.inserting_at(3, vector_to_insert); - // - // outcome: - // augmented_numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] vector inserting_at(size_t index, const std::vector& vector) const - { - return inserting_at_impl(index, vector.cbegin(), vector.cend()); - } - - // Inserts a range of elements starting at the given index, therefore changing the vector's contents (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const std::initializer_list vector_to_insert({9, -5, 6}); - // numbers.insert_at(3, vector_to_insert); - // - // outcome: - // numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - vector& insert_at(size_t index, std::initializer_list list) - { - return insert_at(index, std::vector(std::move(list))); - } - - // Returns a copy by inserting a range of elements starting at the given index (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const std::initializer_list vector_to_insert({9, -5, 6}); - // auto augmented_numbers = numbers.inserting_at(3, vector_to_insert); - // - // outcome: - // augmented_numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] vector inserting_at(size_t index, std::initializer_list list) const - { - return inserting_at(index, std::vector(std::move(list))); - } - - // Inserts a value at the end of the vector in place (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.insert_back(18); - // - // outcome: - // numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7, 1, 18}); - vector& insert_back(T value) - { - m_vector.push_back(value); - return *this; - } - - // Inserts a value at the beginning of the vector in place (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.insert_front(18); - // - // outcome: - // numbers -> fcpp::vector({18, 1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector& insert_front(T value) - { - return insert_at(0, value); - } - - // Makes a copy of the vector, inserts value at the end of the copy and returns the copy (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto augmented_numbers = numbers.inserting_back(18); - // - // outcome: - // augmented_numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7, 1, 18}); - [[nodiscard]] vector inserting_back(T value) const - { - auto augmented_vector(m_vector); - augmented_vector.push_back(value); - return vector(augmented_vector); - } - - // Makes a copy of the vector, inserts value at the beginning of the copy and returns the copy (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto augmented_numbers = numbers.inserting_front(18); - // - // outcome: - // augmented_numbers -> fcpp::vector({18, 1, 4, 2, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] vector inserting_front(T value) const - { - return inserting_at(0, value); - } - - // Inserts a range of values at the end of the vector in place (mutating) - // - // example: - // fcpp::vector numbers({ 4, 5, 6 }); - // numbers.insert_back(fcpp::vector({1, 2, 3})); - // - // outcome: - // numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); - vector& insert_back(const vector& vector) - { - return insert_back_range_impl(vector.begin(), vector.end()); - } - - // Inserts a range of values at the beginning of the vector in place (mutating) - // - // example: - // fcpp::vector numbers({ 4, 5, 6 }); - // numbers.insert_front(fcpp::vector({1, 2, 3})); - // - // outcome: - // numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); - vector& insert_front(const vector& vector) - { - return insert_front_range_impl(vector.begin(), vector.end()); - } - - // Makes a copy of the vector, inserts a range of values at the end of the copy, and returns the copy (non-mutating) - // - // example: - // const fcpp::vector numbers({ 4, 5, 6 }); - // auto augmented_numbers = numbers.inserting_back(fcpp::vector({1, 2, 3})); - // - // outcome: - // augmented_numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); - [[nodiscard]] vector inserting_back(const vector& vector) const - { - return inserting_back_range_impl(vector.begin(), vector.end()); - } - - // Makes a copy of the vector, inserts a range of values at the beginning of the copy, and returns the copy (non-mutating) - // - // example: - // const fcpp::vector numbers({ 4, 5, 6 }); - // auto augmented_numbers = numbers.inserting_front(fcpp::vector({1, 2, 3})); - // - // outcome: - // augmented_numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); - [[nodiscard]] vector inserting_front(const vector& vector) const - { - return inserting_front_range_impl(vector.begin(), vector.end()); - } - - // Inserts a range of values at the end of the vector in place (mutating) - // - // example: - // fcpp::vector numbers({ 4, 5, 6 }); - // numbers.insert_back(std::vector({1, 2, 3})); - // - // outcome: - // numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); - vector& insert_back(const std::vector& vector) - { - return insert_back_range_impl(vector.cbegin(), vector.cend()); - } - - // Inserts a range of values at the beginning of the vector in place (mutating) - // - // example: - // fcpp::vector numbers({ 4, 5, 6 }); - // numbers.insert_front(std::vector({1, 2, 3})); - // - // outcome: - // numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); - vector& insert_front(const std::vector& vector) - { - return insert_front_range_impl(vector.cbegin(), vector.cend()); - } - - // Makes a copy of the vector, inserts a range of values at the end of the copy, and returns the copy (non-mutating) - // - // example: - // const fcpp::vector numbers({ 4, 5, 6 }); - // auto augmented_numbers = numbers.inserting_back(std::vector({1, 2, 3})); - // - // outcome: - // augmented_numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); - [[nodiscard]] vector inserting_back(const std::vector& vector) const - { - return inserting_back_range_impl(vector.cbegin(), vector.cend()); - } - - // Makes a copy of the vector, inserts a range of values at the beginning of the copy, and returns the copy (non-mutating) - // - // example: - // const fcpp::vector numbers({ 4, 5, 6 }); - // auto augmented_numbers = numbers.inserting_front(std::vector({1, 2, 3})); - // - // outcome: - // augmented_numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); - [[nodiscard]] vector inserting_front(const std::vector& vector) const - { - return inserting_front_range_impl(vector.cbegin(), vector.cend()); - } - - // Inserts a range of values at the end of the vector in place (mutating) - // - // example: - // fcpp::vector numbers({ 4, 5, 6 }); - // numbers.insert_back(std::initializer_list({1, 2, 3})); - // - // outcome: - // numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); - vector& insert_back(const std::initializer_list& list) - { - return insert_back(std::vector(list)); - } - - // Inserts a range of values at the beginning of the vector in place (mutating) - // - // example: - // fcpp::vector numbers({ 4, 5, 6 }); - // numbers.insert_front(std::initializer_list({1, 2, 3})); - // - // outcome: - // numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); - vector& insert_front(const std::initializer_list& list) - { - return insert_front(std::vector(list)); - } - - // Makes a copy of the vector, inserts a range of values at the end of the copy, and returns the copy (non-mutating) - // - // example: - // const fcpp::vector numbers({ 4, 5, 6 }); - // auto augmented_numbers = numbers.inserting_back(std::initializer_list({1, 2, 3})); - // - // outcome: - // augmented_numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); - [[nodiscard]] vector inserting_back(const std::initializer_list& list) const - { - return inserting_back(std::vector(list)); - } - - // Makes a copy of the vector, inserts a range of values at the beginning of the copy, and returns the copy (non-mutating) - // - // example: - // const fcpp::vector numbers({ 4, 5, 6 }); - // auto augmented_numbers = numbers.inserting_front(std::initializer_list({1, 2, 3})); - // - // outcome: - // augmented_numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); - [[nodiscard]] vector inserting_front(const std::initializer_list& list) const - { - return inserting_front(std::vector(list)); - } - - // Replaces the existing contents starting at `index` with the contents of the given vector (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.replace_range_at(4, fcpp::vector({9, -10, 8})); - // - // outcome: - // numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - vector& replace_range_at(size_t index, const vector& vector) - { - return replace_range_at_imp(index, vector.begin(), vector.end()); - } - - // Replaces the existing contents starting at `index` with the contents of the given vector (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.replace_range_at(4, std::vector({9, -10, 8})); - // - // outcome: - // numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - vector& replace_range_at(size_t index, const std::vector& vector) - { - return replace_range_at_imp(index, vector.cbegin(), vector.cend()); - } - - // Replaces the existing contents starting at `index` with the contents of the given vector (mutating) - // - // example: - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.replace_range_at(4, std::initializer_list({9, -10, 8})); - // - // outcome: - // numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - vector& replace_range_at(size_t index, const std::initializer_list& list) - { - return replace_range_at(index, std::vector(list)); - } - - // Returns a copy whose elements starting at `index` are replaced with the contents of the given vector (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto replaced_numbers = numbers.replacing_range_at(4, fcpp::vector({9, -10, 8})); - // - // outcome: - // replaced_numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - [[nodiscard]] vector replacing_range_at(size_t index, const vector& vector) const - { - return replacing_range_at_imp(index, vector.begin(), vector.end()); - } - - // Returns a copy whose elements starting at `index` are replaced with the contents of the given vector (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto replaced_numbers = numbers.replacing_range_at(4, std::vector({9, -10, 8})); - // - // outcome: - // replaced_numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - [[nodiscard]] vector replacing_range_at(size_t index, const std::vector& vector) const - { - return replacing_range_at_imp(index, vector.cbegin(), vector.cend()); - } - - // Returns a copy whose elements starting at `index` are replaced with the contents of the given vector (non-mutating) - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto replaced_numbers = numbers.replacing_range_at(4, std::initializer_list({9, -10, 8})); - // - // outcome: - // replaced_numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - [[nodiscard]] vector replacing_range_at(size_t index, const std::initializer_list& list) const - { - return replacing_range_at(index, std::vector(list)); - } - - // Replaces all existing elements with a constant element (mutating) - // - // example: - // fcpp::vector numbers({1, 3, -6, 4, -9}); - // numbers.fill(7); - // - // outcome: - // numbers -> fcpp::vector({ 7, 7, 7, 7, 7 }) - vector& fill(const T& element) - { - std::fill(m_vector.begin(), - m_vector.end(), - element); - return *this; - } - - // Returns the size of the vector (how many elements it contains, it may be different from its capacity) - [[nodiscard]] size_t size() const - { - return m_vector.size(); - } - - // Clears the vector by removing all elements (mutating) - vector& clear() - { - m_vector.clear(); - return *this; - } - - // Returns true if the vector has no elements - [[nodiscard]] bool is_empty() const - { - return m_vector.empty(); - } - - // Returns the underlying capacity of the vector, which can be larger from its size - [[nodiscard]] size_t capacity() const - { - return m_vector.capacity(); - } - - // Reserves the necessary memory for `count` elements, so that subsequent changes in the - // vector's size due to addition/removal of elements is more performant - vector& reserve(size_t count) - { - m_vector.reserve(count); - return *this; - } - - // Resizes the vector to have given number of elements - // If `count` is larger than the current `size`, then `count-size` default elements are inserted at the back - // If `count` is smaller than the current `size`, then the last `size - count` elements are removed - // - // example: - // // numbers.capacity() = 9 - // // numbers.size() = 9 - // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - - // // numbers.capacity() = 9 - // // numbers.size() = 5 - // // numbers -> fcpp::vector({1, 4, 2, 5, 8}); - // numbers.resize(5); - // - // // empty_numbers.capacity() = 0 - // // empty_numbers.size() = 0 - // fcpp::vector empty_numbers; - // - // // empty_numbers.capacity() = 5 - // // empty_numbers.size() = 5 - // // empty_numbers -> fcpp::vector({0, 0, 0, 0, 0}); - // empty_numbers.resize(5); - vector& resize(size_t count) - { - m_vector.resize(count); - return *this; - } - - // Returns the begin iterator, useful for other standard library algorithms - [[nodiscard]] typename std::vector::iterator begin() - { - return m_vector.begin(); - } - - // Returns the const begin iterator, useful for other standard library algorithms - [[nodiscard]] typename std::vector::const_iterator begin() const - { - return m_vector.begin(); - } - - // Returns the end iterator, useful for other standard library algorithms - [[nodiscard]] typename std::vector::iterator end() - { - return m_vector.end(); - } - - // Returns the const end iterator, useful for other standard library algorithms - [[nodiscard]] typename std::vector::const_iterator end() const - { - return m_vector.end(); - } - - // Returns a set, whose elements are the elements of the vector, removing any potential duplicates - // - // example: - // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const auto& unique_numbers = numbers.distinct(); - // - // outcome: - // unique_numbers -> fcpp::set({1, 2, 3, 4, 5, 7, 8}) - template > - set distinct() const - { - return set(*this); - } - - // Returns a reference to the element in the given index, allowing subscripting and value editing. - // Bounds checking (assert) is enabled for debug builds. - T& operator[](size_t index) - { - assert_smaller_size(index); - return m_vector[index]; - } - - // Returns a constant reference to the element in the given index, allowing subscripting. - // Bounds checking (assert) is enabled for debug builds. - const T& operator[](size_t index) const - { - assert_smaller_size(index); - return m_vector[index]; - } - - // Returns true if both instances have equal sizes and the corresponding elements (same index) are equal - bool operator ==(const vector& rhs) const - { -#ifdef CPP17_AVAILABLE - return std::equal(begin(), - end(), - rhs.begin(), - rhs.end()); -#else - if (size() != rhs.size()) { - return false; - } - - for (auto i = 0; i < size(); ++i) { - if (!((*this)[i] == rhs[i])) { - return false; - } - } - - return true; + // Executes the given operation for each element of the vector in parallel. The operation must not + // change the vector's contents during execution. + template >> + const vector& for_each_parallel(Callable && operation) const + { + std::for_each(std::execution::par, + m_vector.cbegin(), + m_vector.cend(), + std::forward(operation)); + return *this; + } #endif - } - - // Returns false if either the sizes are not equal or at least one corresponding element (same index) is not equal - bool operator !=(const vector& rhs) const - { - return !((*this) == rhs); - } - - private: - std::vector m_vector; - // The iterator passed here may not necessarily be from std::vector as long as it's a valid iterable range + + // Returns the first index in which the given element is found in the vector. + // In case of multiple occurrences, only the first index is returned + // (see find_all_indices for multiple occurrences). + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const auto index_of_one = numbers.find_first_index(1); + // const auto index_of_nine = numbers.find_first_index(9); + // + // outcome: + // index_of_one.value() -> 0 + // index_of_one.has_value() -> true + // index_of_nine.has_value() -> false + [[nodiscard]] fcpp::optional_t find_first_index(const T& element) const + { + auto const it = std::find(m_vector.cbegin(), + m_vector.cend(), + element); + if (it != m_vector.cend()) { + auto index = std::distance(m_vector.cbegin(), it); + return index; + } + return fcpp::optional_t(); + } + + // Returns the last index in which the given element is found in the vector. + // In case of multiple occurrences, only the last index is returned + // (see find_all_indices for multiple occurrences). + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, -6, 3, 1, 7, 1}); + // const auto index_of_one = numbers.find_last_index(1); + // const auto index_of_nine = numbers.find_last_index(9); + // + // outcome: + // index_of_one.value() -> 8 + // index_of_one.has_value() -> true + // index_of_nine.has_value() -> false + [[nodiscard]] fcpp::optional_t find_last_index(const T& element) const + { + auto const it = std::find(m_vector.crbegin(), + m_vector.crend(), + element); + if (it != m_vector.crend()) { + auto index = std::distance(it, m_vector.crend()) - 1; + return index; + } + return fcpp::optional_t(); + } + + // Returns all indices in which the given element is found in the vector. + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 9, 1}); + // const auto indices_of_one = numbers.find_all_indices(1); + // const auto indices_of_ten = numbers.find_all_indices(10); + // + // outcome: + // indices_of_one -> { 0, 6, 8 } + // indices_of_ten -> empty vector + [[nodiscard]] std::vector find_all_indices(const T& element) const + { + std::vector indices; + auto it = std::find(m_vector.cbegin(), + m_vector.cend(), + element); + while (it != m_vector.cend()) + { + indices.push_back(std::distance(m_vector.cbegin(), it)); + ++it; + it = std::find(it, m_vector.cend(), element); + } + return indices; + } + + // Removes the element at `index` (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.remove_at(4); + // + // outcome: + // numbers -> fcpp::vector({1, 4, 2, 5, 3, 1, 7, 1}); + vector& remove_at(int index) + { + assert_smaller_size(index); + m_vector.erase(begin() + index); + return *this; + } + + // Returns a copy of itself in which the element at `index` is removed (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto shorter_vector = numbers.removing_at(4); + // + // outcome: + // shorter_vector -> fcpp::vector({1, 4, 2, 5, 3, 1, 7, 1}); + [[nodiscard]] vector removing_at(int index) const + { + assert_smaller_size(index); + auto copy(m_vector); + copy.erase(copy.begin() + index); + return vector(copy); + } + + // Removes the last element, if present (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.remove_back(); + // + // outcome: + // numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7}); + vector& remove_back() + { + m_vector.pop_back(); + return *this; + } + + // Returns a copy of itself in which the last element is removed (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto shorter_vector = numbers.removing_back(); + // + // outcome: + // shorter_vector -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7}); + [[nodiscard]] vector removing_back() const + { + auto copy(m_vector); + copy.pop_back(); + return vector(copy); + } + + // Removes the first element, if present (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.remove_front(); + // + // outcome: + // numbers -> fcpp::vector({4, 2, 5, 8, 3, 1, 7, 1}); + vector& remove_front() + { + if (size() == 0) + { + return *this; + } + return remove_at(0); + } + + // Returns a copy of itself in which the first element is removed (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto shorter_numbers = numbers.removing_front(); + // + // outcome: + // shorter_numbers -> fcpp::vector({4, 2, 5, 8, 3, 1, 7, 1}); + [[nodiscard]] vector removing_front() const + { + if (size() == 0) + { + return *this; + } + return removing_at(0); + } + + // Removes the elements whose index is contained in the given index range (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.remove_range(index_range::start_count(2, 3)); + // + // outcome: + // numbers -> fcpp::vector({ 1, 4, 2, 7, 1 }) + vector& remove_range(index_range range) + { + if (!range.is_valid || size() < range.end + 1) + { + return *this; + } + m_vector.erase(begin() + range.start, + begin() + range.start + range.count); + return *this; + } + + // Returns a copy by removing the elements whose index is contained in the given index range (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const auto shorter_vector = numbers.removing_range(index_range::start_count(2, 3)); + // + // outcome: + // shorter_vector -> fcpp::vector({ 1, 4, 3, 1, 7, 1 }) + [[nodiscard]] vector removing_range(index_range range) const + { + if (!range.is_valid || size() < range.end + 1) + { + return *this; + } + auto shorter_vector(m_vector); + shorter_vector.erase(shorter_vector.begin() + range.start, + shorter_vector.begin() + range.start + range.count); + return vector(shorter_vector); + } + + // Inserts an element at the given index, therefore changing the vector's contents (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.insert_at(3, 18); + // + // outcome: + // numbers -> fcpp::vector({1, 4, 2, 18, 5, 8, 3, 1, 7, 1}); + vector& insert_at(int index, const T& element) + { + assert_smaller_or_equal_size(index); + m_vector.insert(begin() + index, element); + return *this; + } + + // Returns a copy by inserting an element at the given index (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto augmented_numbers = numbers.inserting_at(3, 18); + // + // outcome: + // augmented_numbers -> fcpp::vector({1, 4, 2, 18, 5, 8, 3, 1, 7, 1}); + [[nodiscard]] vector inserting_at(int index, const T& element) const + { + assert_smaller_or_equal_size(index); + auto copy(m_vector); + copy.insert(copy.begin() + index, element); + return vector(copy); + } + + // Inserts a range of elements starting at the given index, therefore changing the vector's contents (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const fcpp::vector vector_to_insert({9, -5, 6}); + // numbers.insert_at(3, vector_to_insert); + // + // outcome: + // numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); + vector& insert_at(int index, const vector& vector) + { + return insert_at_impl(index, vector.begin(), vector.end()); + } + + // Returns a copy by inserting a range of elements starting at the given index (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const fcpp::vector vector_to_insert({9, -5, 6}); + // auto augmented_numbers = numbers.inserting_at(3, vector_to_insert); + // + // outcome: + // augmented_numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); + [[nodiscard]] vector inserting_at(int index, const vector& vector) const + { + return inserting_at_impl(index, vector.begin(), vector.end()); + } + + // Inserts a range of elements starting at the given index, therefore changing the vector's contents (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const std::vector vector_to_insert({9, -5, 6}); + // numbers.insert_at(3, vector_to_insert); + // + // outcome: + // numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); + vector& insert_at(int index, const std::vector& vector) + { + return insert_at_impl(index, vector.cbegin(), vector.cend()); + } + + // Returns a copy by inserting a range of elements starting at the given index (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const std::vector vector_to_insert({9, -5, 6}); + // auto augmented_numbers = numbers.inserting_at(3, vector_to_insert); + // + // outcome: + // augmented_numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); + [[nodiscard]] vector inserting_at(int index, const std::vector& vector) const + { + return inserting_at_impl(index, vector.cbegin(), vector.cend()); + } + + // Inserts a range of elements starting at the given index, therefore changing the vector's contents (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const std::initializer_list vector_to_insert({9, -5, 6}); + // numbers.insert_at(3, vector_to_insert); + // + // outcome: + // numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); + vector& insert_at(int index, std::initializer_list list) + { + return insert_at(index, std::vector(std::move(list))); + } + + // Returns a copy by inserting a range of elements starting at the given index (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const std::initializer_list vector_to_insert({9, -5, 6}); + // auto augmented_numbers = numbers.inserting_at(3, vector_to_insert); + // + // outcome: + // augmented_numbers -> fcpp::vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); + [[nodiscard]] vector inserting_at(int index, std::initializer_list list) const + { + return inserting_at(index, std::vector(std::move(list))); + } + + // Inserts a value at the end of the vector in place (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.insert_back(18); + // + // outcome: + // numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7, 1, 18}); + vector& insert_back(T value) + { + m_vector.push_back(value); + return *this; + } + + // Inserts a value at the beginning of the vector in place (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.insert_front(18); + // + // outcome: + // numbers -> fcpp::vector({18, 1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector& insert_front(T value) + { + return insert_at(0, value); + } + + // Makes a copy of the vector, inserts value at the end of the copy and returns the copy (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto augmented_numbers = numbers.inserting_back(18); + // + // outcome: + // augmented_numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7, 1, 18}); + [[nodiscard]] vector inserting_back(T value) const + { + auto augmented_vector(m_vector); + augmented_vector.push_back(value); + return vector(augmented_vector); + } + + // Makes a copy of the vector, inserts value at the beginning of the copy and returns the copy (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto augmented_numbers = numbers.inserting_front(18); + // + // outcome: + // augmented_numbers -> fcpp::vector({18, 1, 4, 2, 5, 8, 3, 1, 7, 1}); + [[nodiscard]] vector inserting_front(T value) const + { + return inserting_at(0, value); + } + + // Inserts a range of values at the end of the vector in place (mutating) + // + // example: + // fcpp::vector numbers({ 4, 5, 6 }); + // numbers.insert_back(fcpp::vector({1, 2, 3})); + // + // outcome: + // numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); + vector& insert_back(const vector& vector) + { + return insert_back_range_impl(vector.begin(), vector.end()); + } + + // Inserts a range of values at the beginning of the vector in place (mutating) + // + // example: + // fcpp::vector numbers({ 4, 5, 6 }); + // numbers.insert_front(fcpp::vector({1, 2, 3})); + // + // outcome: + // numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); + vector& insert_front(const vector& vector) + { + return insert_front_range_impl(vector.begin(), vector.end()); + } + + // Makes a copy of the vector, inserts a range of values at the end of the copy, and returns the copy (non-mutating) + // + // example: + // const fcpp::vector numbers({ 4, 5, 6 }); + // auto augmented_numbers = numbers.inserting_back(fcpp::vector({1, 2, 3})); + // + // outcome: + // augmented_numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); + [[nodiscard]] vector inserting_back(const vector& vector) const + { + return inserting_back_range_impl(vector.begin(), vector.end()); + } + + // Makes a copy of the vector, inserts a range of values at the beginning of the copy, and returns the copy (non-mutating) + // + // example: + // const fcpp::vector numbers({ 4, 5, 6 }); + // auto augmented_numbers = numbers.inserting_front(fcpp::vector({1, 2, 3})); + // + // outcome: + // augmented_numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); + [[nodiscard]] vector inserting_front(const vector& vector) const + { + return inserting_front_range_impl(vector.begin(), vector.end()); + } + + // Inserts a range of values at the end of the vector in place (mutating) + // + // example: + // fcpp::vector numbers({ 4, 5, 6 }); + // numbers.insert_back(std::vector({1, 2, 3})); + // + // outcome: + // numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); + vector& insert_back(const std::vector& vector) + { + return insert_back_range_impl(vector.cbegin(), vector.cend()); + } + + // Inserts a range of values at the beginning of the vector in place (mutating) + // + // example: + // fcpp::vector numbers({ 4, 5, 6 }); + // numbers.insert_front(std::vector({1, 2, 3})); + // + // outcome: + // numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); + vector& insert_front(const std::vector& vector) + { + return insert_front_range_impl(vector.cbegin(), vector.cend()); + } + + // Makes a copy of the vector, inserts a range of values at the end of the copy, and returns the copy (non-mutating) + // + // example: + // const fcpp::vector numbers({ 4, 5, 6 }); + // auto augmented_numbers = numbers.inserting_back(std::vector({1, 2, 3})); + // + // outcome: + // augmented_numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); + [[nodiscard]] vector inserting_back(const std::vector& vector) const + { + return inserting_back_range_impl(vector.cbegin(), vector.cend()); + } + + // Makes a copy of the vector, inserts a range of values at the beginning of the copy, and returns the copy (non-mutating) + // + // example: + // const fcpp::vector numbers({ 4, 5, 6 }); + // auto augmented_numbers = numbers.inserting_front(std::vector({1, 2, 3})); + // + // outcome: + // augmented_numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); + [[nodiscard]] vector inserting_front(const std::vector& vector) const + { + return inserting_front_range_impl(vector.cbegin(), vector.cend()); + } + + // Inserts a range of values at the end of the vector in place (mutating) + // + // example: + // fcpp::vector numbers({ 4, 5, 6 }); + // numbers.insert_back(std::initializer_list({1, 2, 3})); + // + // outcome: + // numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); + vector& insert_back(const std::initializer_list& list) + { + return insert_back(std::vector(list)); + } + + // Inserts a range of values at the beginning of the vector in place (mutating) + // + // example: + // fcpp::vector numbers({ 4, 5, 6 }); + // numbers.insert_front(std::initializer_list({1, 2, 3})); + // + // outcome: + // numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); + vector& insert_front(const std::initializer_list& list) + { + return insert_front(std::vector(list)); + } + + // Makes a copy of the vector, inserts a range of values at the end of the copy, and returns the copy (non-mutating) + // + // example: + // const fcpp::vector numbers({ 4, 5, 6 }); + // auto augmented_numbers = numbers.inserting_back(std::initializer_list({1, 2, 3})); + // + // outcome: + // augmented_numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); + [[nodiscard]] vector inserting_back(const std::initializer_list& list) const + { + return inserting_back(std::vector(list)); + } + + // Makes a copy of the vector, inserts a range of values at the beginning of the copy, and returns the copy (non-mutating) + // + // example: + // const fcpp::vector numbers({ 4, 5, 6 }); + // auto augmented_numbers = numbers.inserting_front(std::initializer_list({1, 2, 3})); + // + // outcome: + // augmented_numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); + [[nodiscard]] vector inserting_front(const std::initializer_list& list) const + { + return inserting_front(std::vector(list)); + } + + // Replaces the existing contents starting at `index` with the contents of the given vector (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.replace_range_at(4, fcpp::vector({9, -10, 8})); + // + // outcome: + // numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) + vector& replace_range_at(int index, const vector& vector) + { + return replace_range_at_imp(index, vector.begin(), vector.end()); + } + + // Replaces the existing contents starting at `index` with the contents of the given vector (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.replace_range_at(4, std::vector({9, -10, 8})); + // + // outcome: + // numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) + vector& replace_range_at(int index, const std::vector& vector) + { + return replace_range_at_imp(index, vector.cbegin(), vector.cend()); + } + + // Replaces the existing contents starting at `index` with the contents of the given vector (mutating) + // + // example: + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.replace_range_at(4, std::initializer_list({9, -10, 8})); + // + // outcome: + // numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) + vector& replace_range_at(int index, const std::initializer_list& list) + { + return replace_range_at(index, std::vector(list)); + } + + // Returns a copy whose elements starting at `index` are replaced with the contents of the given vector (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto replaced_numbers = numbers.replacing_range_at(4, fcpp::vector({9, -10, 8})); + // + // outcome: + // replaced_numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) + [[nodiscard]] vector replacing_range_at(int index, const vector& vector) const + { + return replacing_range_at_imp(index, vector.begin(), vector.end()); + } + + // Returns a copy whose elements starting at `index` are replaced with the contents of the given vector (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto replaced_numbers = numbers.replacing_range_at(4, std::vector({9, -10, 8})); + // + // outcome: + // replaced_numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) + [[nodiscard]] vector replacing_range_at(int index, const std::vector& vector) const + { + return replacing_range_at_imp(index, vector.cbegin(), vector.cend()); + } + + // Returns a copy whose elements starting at `index` are replaced with the contents of the given vector (non-mutating) + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // auto replaced_numbers = numbers.replacing_range_at(4, std::initializer_list({9, -10, 8})); + // + // outcome: + // replaced_numbers -> fcpp::vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) + [[nodiscard]] vector replacing_range_at(int index, const std::initializer_list& list) const + { + return replacing_range_at(index, std::vector(list)); + } + + // Replaces all existing elements with a constant element (mutating) + // + // example: + // fcpp::vector numbers({1, 3, -6, 4, -9}); + // numbers.fill(7); + // + // outcome: + // numbers -> fcpp::vector({ 7, 7, 7, 7, 7 }) + vector& fill(const T& element) + { + std::fill(m_vector.begin(), + m_vector.end(), + element); + return *this; + } + + // Returns the size of the vector (how many elements it contains, it may be different from its capacity) + [[nodiscard]] size_t size() const + { + return m_vector.size(); + } + + // Clears the vector by removing all elements (mutating) + vector& clear() + { + m_vector.clear(); + return *this; + } + + // Returns true if the vector has no elements + [[nodiscard]] bool is_empty() const + { + return m_vector.empty(); + } + + // Returns the underlying capacity of the vector, which can be larger from its size + [[nodiscard]] size_t capacity() const + { + return m_vector.capacity(); + } + + // Reserves the necessary memory for `count` elements, so that subsequent changes in the + // vector's size due to addition/removal of elements is more performant + vector& reserve(size_t count) + { + m_vector.reserve(count); + return *this; + } + + // Resizes the vector to have given number of elements + // If `count` is larger than the current `size`, then `count-size` default elements are inserted at the back + // If `count` is smaller than the current `size`, then the last `size - count` elements are removed + // + // example: + // // numbers.capacity() = 9 + // // numbers.size() = 9 + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + + // // numbers.capacity() = 9 + // // numbers.size() = 5 + // // numbers -> fcpp::vector({1, 4, 2, 5, 8}); + // numbers.resize(5); + // + // // empty_numbers.capacity() = 0 + // // empty_numbers.size() = 0 + // fcpp::vector empty_numbers; + // + // // empty_numbers.capacity() = 5 + // // empty_numbers.size() = 5 + // // empty_numbers -> fcpp::vector({0, 0, 0, 0, 0}); + // empty_numbers.resize(5); + vector& resize(size_t count) + { + m_vector.resize(count); + return *this; + } + + // Returns the begin iterator, useful for other standard library algorithms + [[nodiscard]] typename std::vector::iterator begin() + { + return m_vector.begin(); + } + + // Returns the const begin iterator, useful for other standard library algorithms + [[nodiscard]] typename std::vector::const_iterator begin() const + { + return m_vector.begin(); + } + + // Returns the end iterator, useful for other standard library algorithms + [[nodiscard]] typename std::vector::iterator end() + { + return m_vector.end(); + } + + // Returns the const end iterator, useful for other standard library algorithms + [[nodiscard]] typename std::vector::const_iterator end() const + { + return m_vector.end(); + } + + // Returns a set, whose elements are the elements of the vector, removing any potential duplicates + // + // example: + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const auto& unique_numbers = numbers.distinct(); + // + // outcome: + // unique_numbers -> fcpp::set({1, 2, 3, 4, 5, 7, 8}) + template > + set distinct() const { + return set(*this); + } + + // Returns a reference to the element in the given index, allowing subscripting and value editing. + // Bounds checking (assert) is enabled for debug builds. + T& operator[](int index) + { + assert_smaller_size(index); + return m_vector[index]; + } + + // Returns a constant reference to the element in the given index, allowing subscripting. + // Bounds checking (assert) is enabled for debug builds. + const T& operator[](int index) const + { + assert_smaller_size(index); + return m_vector[index]; + } + + // Returns true if both instances have equal sizes and the corresponding elements (same index) are equal + bool operator ==(const vector& rhs) const + { #ifdef CPP17_AVAILABLE - template ::value_type>>> + return std::equal(begin(), + end(), + rhs.begin(), + rhs.end()); #else - template + if (size() != rhs.size()) { + return false; + } + + for (auto i = 0; i < size(); ++i) { + if (!((*this)[i] == rhs[i])) { + return false; + } + } + + return true; #endif - vector& insert_back_range_impl(const Iterator& vec_begin, const Iterator& vec_end) - { - m_vector.insert(m_vector.end(), - vec_begin, - vec_end); - return *this; - } - + } + + // Returns false if either the sizes are not equal or at least one corresponding element (same index) is not equal + bool operator !=(const vector& rhs) const + { + return !((*this) == rhs); + } + +private: + std::vector m_vector; + // The iterator passed here may not necessarily be from std::vector as long as it's a valid iterable range #ifdef CPP17_AVAILABLE - template ::value_type>>> + template::value_type>>> #else - template + template #endif - vector& insert_front_range_impl(const Iterator& vec_begin, const Iterator& vec_end) - { - m_vector.insert(m_vector.begin(), - vec_begin, - vec_end); - return *this; - } - + vector& insert_back_range_impl(const Iterator& vec_begin, const Iterator& vec_end) + { + m_vector.insert(m_vector.end(), + vec_begin, + vec_end); + return *this; + } + #ifdef CPP17_AVAILABLE - template ::value_type>>> + template::value_type>>> #else - template + template #endif - [[nodiscard]] vector inserting_back_range_impl(const Iterator& vec_begin, const Iterator& vec_end) const - { - auto augmented_vector(m_vector); - augmented_vector.reserve(augmented_vector.size() + std::distance(vec_begin, vec_end)); - augmented_vector.insert(augmented_vector.end(), - vec_begin, - vec_end); - return vector(augmented_vector); - } - + vector& insert_front_range_impl(const Iterator& vec_begin, const Iterator& vec_end) + { + m_vector.insert(m_vector.begin(), + vec_begin, + vec_end); + return *this; + } + #ifdef CPP17_AVAILABLE - template ::value_type>>> + template::value_type>>> #else - template + template #endif - [[nodiscard]] vector inserting_front_range_impl(const Iterator& vec_begin, const Iterator& vec_end) const - { - auto augmented_vector(m_vector); - augmented_vector.reserve(augmented_vector.size() + std::distance(vec_begin, vec_end)); - augmented_vector.insert(augmented_vector.begin(), - vec_begin, - vec_end); - return vector(augmented_vector); - } - + [[nodiscard]] vector inserting_back_range_impl(const Iterator& vec_begin, const Iterator& vec_end) const + { + auto augmented_vector(m_vector); + augmented_vector.reserve(augmented_vector.size() + std::distance(vec_begin, vec_end)); + augmented_vector.insert(augmented_vector.end(), + vec_begin, + vec_end); + return vector(augmented_vector); + } + #ifdef CPP17_AVAILABLE - template ::value>> - [[nodiscard]] auto zip_impl(const Iterator& vec_begin, const Iterator& vec_end) const -> - vector>> - { - using U = deref_type; + template::value_type>>> #else - template - [[nodiscard]] vector> zip_impl(const typename std::vector::const_iterator& vec_begin, - const typename std::vector::const_iterator& vec_end) const - { + template #endif - const auto vec_size = std::distance(vec_begin, vec_end); - assert(m_vector.size() == vec_size); - std::vector> combined_vector; - combined_vector.reserve(vec_size); - for (size_t i = 0; i < vec_size; ++i) { - combined_vector.push_back({m_vector[i], *(vec_begin + i)}); - } - return vector>(std::move(combined_vector)); - } - + [[nodiscard]] vector inserting_front_range_impl(const Iterator& vec_begin, const Iterator& vec_end) const + { + auto augmented_vector(m_vector); + augmented_vector.reserve(augmented_vector.size() + std::distance(vec_begin, vec_end)); + augmented_vector.insert(augmented_vector.begin(), + vec_begin, + vec_end); + return vector(augmented_vector); + } + #ifdef CPP17_AVAILABLE - // checks if the value of dereferencing the passed Iterators is convertible to type T - template ::value_type>>> + template::value>> + [[nodiscard]] auto zip_impl( const Iterator& vec_begin, const Iterator& vec_end) const -> + vector>> + { + using U = deref_type; #else - template + template + [[nodiscard]] vector> zip_impl(const typename std::vector::const_iterator& vec_begin, + const typename std::vector::const_iterator& vec_end) const + { #endif - vector& insert_at_impl(size_t index, - const Iterator& vec_begin, - const Iterator& vec_end) - { - if (vec_begin != vec_end) { - assert_smaller_or_equal_size(index); - m_vector.insert(begin() + index, - vec_begin, - vec_end); - } - return *this; - } - + const auto vec_size = std::distance(vec_begin, vec_end); + assert(m_vector.size() == vec_size); + std::vector> combined_vector; + combined_vector.reserve(vec_size); + for (size_t i = 0; i < vec_size; ++i) + { + combined_vector.push_back({m_vector[i], *(vec_begin + i)}); + } + return vector>(std::move(combined_vector)); + } + #ifdef CPP17_AVAILABLE - template ::value_type>>> + // checks if the value of dereferencing the passed Iterators is convertible to type T + template::value_type>>> #else - template + template #endif - [[nodiscard]] vector inserting_at_impl(size_t index, - const Iterator& vec_begin, - const Iterator& vec_end) const - { - if (vec_begin == vec_end) { - return *this; - } - assert_smaller_or_equal_size(index); - auto augmented_vector(m_vector); - augmented_vector.insert(augmented_vector.begin() + index, - vec_begin, - vec_end); - return vector(std::move(augmented_vector)); - } - + vector& insert_at_impl(int index, + const Iterator& vec_begin, + const Iterator& vec_end) + { + if (vec_begin != vec_end) + { + assert_smaller_or_equal_size(index); + m_vector.insert(begin() + index, + vec_begin, + vec_end); + } + return *this; + } + #ifdef CPP17_AVAILABLE - template ::value_type>>> + template::value_type>>> #else - template + template #endif - vector& replace_range_at_imp(size_t index, - const Iterator& vec_begin, - const Iterator& vec_end) - { - const auto vec_size = std::distance(vec_begin, vec_end); - assert(index + vec_size >= vec_size && index + vec_size <= size()); - std::copy(vec_begin, - vec_end, - m_vector.begin() + index); - return *this; - } - + [[nodiscard]] vector inserting_at_impl(int index, + const Iterator& vec_begin, + const Iterator& vec_end) const + { + if (vec_begin == vec_end) + { + return *this; + } + assert_smaller_or_equal_size(index); + auto augmented_vector(m_vector); + augmented_vector.insert(augmented_vector.begin() + index, + vec_begin, + vec_end); + return vector(std::move(augmented_vector)); + } + #ifdef CPP17_AVAILABLE - template ::value_type>>> + template::value_type>>> #else - template + template #endif - [[nodiscard]] vector replacing_range_at_imp(size_t index, - const Iterator& vec_begin, - const Iterator& vec_end) const - { - const auto vec_size = std::distance(vec_begin, vec_end); - assert(index + vec_size >= vec_size && index + vec_size <= size()); - auto replaced_vector(m_vector); - std::copy(vec_begin, - vec_end, - replaced_vector.begin() + index); - return vector(replaced_vector); - } - - void assert_smaller_size(size_t index) const - { - assert(index < size()); - } - - void assert_smaller_or_equal_size(size_t index) const - { - assert(index <= size()); - } - }; + vector& replace_range_at_imp(int index, + const Iterator& vec_begin, + const Iterator& vec_end) + { + const auto vec_size = std::distance(vec_begin, vec_end); + assert(index + vec_size >= vec_size && index + vec_size <= size()); + std::copy(vec_begin, + vec_end, + m_vector.begin() + index); + return *this; + } + +#ifdef CPP17_AVAILABLE + template::value_type>>> +#else + template +#endif + [[nodiscard]] vector replacing_range_at_imp(int index, + const Iterator& vec_begin, + const Iterator& vec_end) const + { + const auto vec_size = std::distance(vec_begin, vec_end); + assert(index + vec_size >= vec_size && index + vec_size <= size()); + auto replaced_vector(m_vector); + std::copy(vec_begin, + vec_end, + replaced_vector.begin() + index); + return vector(replaced_vector); + } + + void assert_smaller_size(int index) const + { + assert(index < size() && index >= 0); + } + + void assert_smaller_or_equal_size(int index) const + { + assert(index <= size() && index >= 0); + } +}; + } diff --git a/src/index_range.cc b/src/index_range.cc index f31c472..ac8ceb4 100644 --- a/src/index_range.cc +++ b/src/index_range.cc @@ -25,32 +25,32 @@ index_range index_range::invalid = start_count(-1, -1); index_range::index_range(int start, int count) - : start(-1), end(-1), count(-1) +: start(-1), end(-1), count(-1) { - is_valid = start >= 0 && count > 0; - if (is_valid) { - this->start = start; - this->count = count; - end = start + count - 1; - } + is_valid = start >= 0 && count > 0; + if (is_valid) { + this->start = start; + this->count = count; + end = start + count - 1; + } } index_range index_range::start_count(int start, int count) { - return index_range(start, count); + return index_range(start, count); } index_range index_range::start_end(int start, int end) { - return index_range(start, end - start + 1); + return index_range(start, end - start + 1); } -bool index_range::operator ==(const index_range& rhs) const +bool index_range::operator == (const index_range& rhs) const { - return start == rhs.start && count == rhs.count; + return start == rhs.start && count == rhs.count; } -bool index_range::operator !=(const index_range& rhs) const +bool index_range::operator != (const index_range& rhs) const { - return !(*this == rhs); + return !(*this == rhs); } diff --git a/tests/index_range_test.cc b/tests/index_range_test.cc index b0a6a94..a6cbc0e 100644 --- a/tests/index_range_test.cc +++ b/tests/index_range_test.cc @@ -23,94 +23,89 @@ #include #include "index_range.h" -TEST(RangeTest, InvalidTest) -{ - auto range = index_range::start_count(0, 0); - EXPECT_FALSE(range.is_valid); - EXPECT_EQ(-1, range.start); - EXPECT_EQ(-1, range.end); - EXPECT_EQ(-1, range.count); - - range = index_range::start_count(0, -1); - EXPECT_FALSE(range.is_valid); - EXPECT_EQ(-1, range.start); - EXPECT_EQ(-1, range.end); - EXPECT_EQ(-1, range.count); - - range = index_range::start_count(0, -5); - EXPECT_FALSE(range.is_valid); - EXPECT_EQ(-1, range.start); - EXPECT_EQ(-1, range.end); - EXPECT_EQ(-1, range.count); - - range = index_range::start_count(-1, 10); - EXPECT_FALSE(range.is_valid); - EXPECT_EQ(-1, range.start); - EXPECT_EQ(-1, range.end); - EXPECT_EQ(-1, range.count); - - range = index_range::start_count(-3, 10); - EXPECT_FALSE(range.is_valid); - EXPECT_EQ(-1, range.start); - EXPECT_EQ(-1, range.end); - EXPECT_EQ(-1, range.count); +TEST(RangeTest, InvalidTest) { + auto range = index_range::start_count(0, 0); + EXPECT_FALSE(range.is_valid); + EXPECT_EQ(-1, range.start); + EXPECT_EQ(-1, range.end); + EXPECT_EQ(-1, range.count); + + range = index_range::start_count(0, -1); + EXPECT_FALSE(range.is_valid); + EXPECT_EQ(-1, range.start); + EXPECT_EQ(-1, range.end); + EXPECT_EQ(-1, range.count); + + range = index_range::start_count(0, -5); + EXPECT_FALSE(range.is_valid); + EXPECT_EQ(-1, range.start); + EXPECT_EQ(-1, range.end); + EXPECT_EQ(-1, range.count); + + range = index_range::start_count(-1, 10); + EXPECT_FALSE(range.is_valid); + EXPECT_EQ(-1, range.start); + EXPECT_EQ(-1, range.end); + EXPECT_EQ(-1, range.count); + + range = index_range::start_count(-3, 10); + EXPECT_FALSE(range.is_valid); + EXPECT_EQ(-1, range.start); + EXPECT_EQ(-1, range.end); + EXPECT_EQ(-1, range.count); } -TEST(RangeTest, ValidFromStartAndCountTest) -{ - auto range = index_range::start_count(0, 1); - EXPECT_TRUE(range.is_valid); - EXPECT_EQ(0, range.start); - EXPECT_EQ(0, range.end); - EXPECT_EQ(1, range.count); - - range = index_range::start_count(13, 3); - EXPECT_TRUE(range.is_valid); - EXPECT_EQ(13, range.start); - EXPECT_EQ(15, range.end); - EXPECT_EQ(3, range.count); +TEST(RangeTest, ValidFromStartAndCountTest) { + auto range = index_range::start_count(0, 1); + EXPECT_TRUE(range.is_valid); + EXPECT_EQ(0, range.start); + EXPECT_EQ(0, range.end); + EXPECT_EQ(1, range.count); + + range = index_range::start_count(13, 3); + EXPECT_TRUE(range.is_valid); + EXPECT_EQ(13, range.start); + EXPECT_EQ(15, range.end); + EXPECT_EQ(3, range.count); } -TEST(RangeTest, ValidFromStartAndEndTest) -{ - auto range = index_range::start_end(0, 1); - EXPECT_TRUE(range.is_valid); - EXPECT_EQ(0, range.start); - EXPECT_EQ(1, range.end); - EXPECT_EQ(2, range.count); - - range = index_range::start_end(13, 15); - EXPECT_TRUE(range.is_valid); - EXPECT_EQ(13, range.start); - EXPECT_EQ(15, range.end); - EXPECT_EQ(3, range.count); - - range = index_range::start_end(13, 13); - EXPECT_TRUE(range.is_valid); - EXPECT_EQ(13, range.start); - EXPECT_EQ(13, range.end); - EXPECT_EQ(1, range.count); +TEST(RangeTest, ValidFromStartAndEndTest) { + auto range = index_range::start_end(0, 1); + EXPECT_TRUE(range.is_valid); + EXPECT_EQ(0, range.start); + EXPECT_EQ(1, range.end); + EXPECT_EQ(2, range.count); + + range = index_range::start_end(13, 15); + EXPECT_TRUE(range.is_valid); + EXPECT_EQ(13, range.start); + EXPECT_EQ(15, range.end); + EXPECT_EQ(3, range.count); + + range = index_range::start_end(13, 13); + EXPECT_TRUE(range.is_valid); + EXPECT_EQ(13, range.start); + EXPECT_EQ(13, range.end); + EXPECT_EQ(1, range.count); } -TEST(RangeTest, InvalidFromStartAndEndTest) -{ - const auto range = index_range::start_end(10, 9); - EXPECT_FALSE(range.is_valid); - EXPECT_EQ(-1, range.start); - EXPECT_EQ(-1, range.end); - EXPECT_EQ(-1, range.count); +TEST(RangeTest, InvalidFromStartAndEndTest) { + const auto range = index_range::start_end(10, 9); + EXPECT_FALSE(range.is_valid); + EXPECT_EQ(-1, range.start); + EXPECT_EQ(-1, range.end); + EXPECT_EQ(-1, range.count); } -TEST(RangeTest, EqualityTest) -{ - EXPECT_FALSE(index_range::invalid == index_range::start_end(9, 10)); - EXPECT_TRUE(index_range::invalid == index_range::start_end(10, 9)); - EXPECT_TRUE(index_range::invalid == index_range::invalid); - EXPECT_FALSE(index_range::invalid != index_range::invalid); - - EXPECT_TRUE(index_range::start_end(9, 10) == index_range::start_end(9, 10)); - EXPECT_FALSE(index_range::start_end(9, 10) != index_range::start_end(9, 10)); - - EXPECT_FALSE(index_range::start_end(9, 10) == index_range::start_end(8, 10)); - EXPECT_TRUE(index_range::start_end(9, 10) != index_range::start_end(8, 10)); +TEST(RangeTest, EqualityTest) { + EXPECT_FALSE(index_range::invalid == index_range::start_end(9, 10)); + EXPECT_TRUE(index_range::invalid == index_range::start_end(10, 9)); + EXPECT_TRUE(index_range::invalid == index_range::invalid); + EXPECT_FALSE(index_range::invalid != index_range::invalid); + + EXPECT_TRUE(index_range::start_end(9, 10) == index_range::start_end(9, 10)); + EXPECT_FALSE(index_range::start_end(9, 10) != index_range::start_end(9, 10)); + + EXPECT_FALSE(index_range::start_end(9, 10) == index_range::start_end(8, 10)); + EXPECT_TRUE(index_range::start_end(9, 10) != index_range::start_end(8, 10)); } diff --git a/tests/optional_test.cc b/tests/optional_test.cc index e1e810d..1ccf19b 100644 --- a/tests/optional_test.cc +++ b/tests/optional_test.cc @@ -25,86 +25,20 @@ using namespace fcpp; -TEST(OptionalTest, InvalidTest) -{ - const optional_t index; - EXPECT_FALSE(index.has_value()); +TEST(OptionalTest, InvalidTest) { + const optional_t index; + EXPECT_FALSE(index.has_value()); } -TEST(OptionalTest, ValidTest) -{ - const optional_t index(5); - EXPECT_TRUE(index.has_value()); - EXPECT_EQ(5, index.value()); +TEST(OptionalTest, ValidTest) { + const optional_t index(5); + EXPECT_TRUE(index.has_value()); + EXPECT_EQ(5, index.value()); } -TEST(OptionalTest, AssignmentFromValueTest) -{ - optional_t index(5); - index = 3; - EXPECT_TRUE(index.has_value()); - EXPECT_EQ(3, index.value()); -} - -TEST(OptionalTest, AssignmentFromOptionalTest) -{ - optional_t v1(5); - const optional_t v2(2); - v1 = v2; - EXPECT_TRUE(v1.has_value()); - EXPECT_EQ(2, v1.value()); - EXPECT_TRUE(v2.has_value()); - EXPECT_EQ(2, v2.value()); -} - -TEST(OptionalTest, AssignmentFromNullOptionalTest) -{ - optional_t v1(5); - const optional_t v2; - v1 = v2; - EXPECT_FALSE(v1.has_value()); - EXPECT_FALSE(v2.has_value()); -} - -TEST(OptionalTest, AssignmentToNullFromValueTest) -{ - optional_t index; - index = 3; - EXPECT_TRUE(index.has_value()); - EXPECT_EQ(3, index.value()); -} - -TEST(OptionalTest, AssignmentToNullFromOptionalTest) -{ - optional_t v1; - const optional_t v2(2); - v1 = v2; - EXPECT_TRUE(v1.has_value()); - EXPECT_EQ(2, v1.value()); - EXPECT_TRUE(v2.has_value()); - EXPECT_EQ(2, v2.value()); -} - -TEST(OptionalTest, AssignmentToNullFromNullOptionalTest) -{ - optional_t v1; - const optional_t v2; - v1 = v2; - EXPECT_FALSE(v1.has_value()); - EXPECT_FALSE(v2.has_value()); -} - -TEST(OptionalTest, CopyConstructorTest) -{ - const optional_t v2(5); - const optional_t v1(v2); - EXPECT_TRUE(v1.has_value()); - EXPECT_EQ(5, v2.value()); -} - -TEST(OptionalTest, CopyConstructorNullTest) -{ - const optional_t v2; - const optional_t v1(v2); - EXPECT_FALSE(v1.has_value()); +TEST(OptionalTest, AssignmentTest) { + optional_t index(5); + index = 3; + EXPECT_TRUE(index.has_value()); + EXPECT_EQ(3, index.value()); } diff --git a/tests/set_test.cc b/tests/set_test.cc index 352f767..48fe52e 100644 --- a/tests/set_test.cc +++ b/tests/set_test.cc @@ -31,541 +31,540 @@ using namespace fcpp; template void debug(set& set) { - set.for_each([](const T& element){ - std::cout << element << std::endl; - }); + set.for_each([](const T& element) { + std::cout << element << std::endl; + }); } -void test_contents(const set& set) -{ - EXPECT_EQ(3, set.size()); - EXPECT_EQ(1, set[0]); - EXPECT_EQ(3, set[1]); - EXPECT_EQ(5, set[2]); +void test_contents(const set& set) { + EXPECT_EQ(3, set.size()); + EXPECT_EQ(1, set[0]); + EXPECT_EQ(3, set[1]); + EXPECT_EQ(5, set[2]); } TEST(SetTest, EmptyConstructor) { const set set_under_test; - EXPECT_EQ(0, set_under_test.size()); + EXPECT_EQ(0, set_under_test.size()); } TEST(SetTest, StdSetConstructor) { const set set_under_test(std::set({1, 5, 3, 3})); - test_contents(set_under_test); + test_contents(set_under_test); } TEST(SetTest, StdVectorConstructor) { const set set_under_test(std::vector({1, 5, 3, 3})); - test_contents(set_under_test); + test_contents(set_under_test); } TEST(SetTest, FunctionalVectorConstructor) { const set set_under_test(vector({1, 5, 3, 3})); - test_contents(set_under_test); + test_contents(set_under_test); } TEST(SetTest, StdInitializerListConstructor) { const set set_under_test(std::initializer_list({1, 5, 3, 3})); - test_contents(set_under_test); + test_contents(set_under_test); } TEST(SetTest, Subscripting) { const set set_under_test(std::set({1, 5, 3, 3})); - test_contents(set_under_test); + test_contents(set_under_test); } TEST(SetTest, ConstSubscripting) { - const set set_under_test(std::set({1, 5, 3, 3})); - test_contents(set_under_test); + const set set_under_test(std::set({1, 5, 3, 3})); + test_contents(set_under_test); } TEST(SetTest, Difference) { - const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); - const set set2(std::set({2, 5, 7, 10, 15, 17})); - const auto& diff = set1.difference_with(set2); - EXPECT_EQ(set({1, 3, 8}), diff); + const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); + const set set2(std::set({2, 5, 7, 10, 15, 17})); + const auto& diff = set1.difference_with(set2); + EXPECT_EQ(set({1, 3, 8}), diff); } TEST(SetTest, DifferenceStdSet) { - const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); - const std::set set2({2, 5, 7, 10, 15, 17}); - const auto& diff = set1.difference_with(set2); - EXPECT_EQ(set({1, 3, 8}), diff); + const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); + const std::set set2({2, 5, 7, 10, 15, 17}); + const auto& diff = set1.difference_with(set2); + EXPECT_EQ(set({1, 3, 8}), diff); } TEST(SetTest, DifferenceFunctionalSet) { - const set set1({1, 2, 3, 5, 7, 8, 10}); - const set set2({2, 5, 7, 10, 15, 17}); - const auto& diff = set1.difference_with(set2); - EXPECT_EQ(set({1, 3, 8}), diff); + const set set1({1, 2, 3, 5, 7, 8, 10}); + const set set2({2, 5, 7, 10, 15, 17}); + const auto& diff = set1.difference_with(set2); + EXPECT_EQ(set({1, 3, 8}), diff); } TEST(SetTest, DifferenceFunctionalSetCustomType) { - const set set1({ - person(51, "George"), - person(81, "Jackie"), - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); - - const set set2({ - person(51, "George"), - person(81, "Jackie"), - }); - - const auto& diff = set1.difference_with(set2); - - const set expected({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); - - EXPECT_EQ(expected, diff); + const set set1({ + person(51, "George"), + person(81, "Jackie"), + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + const set set2({ + person(51, "George"), + person(81, "Jackie"), + }); + + const auto& diff = set1.difference_with(set2); + + const set expected({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + EXPECT_EQ(expected, diff); } TEST(SetTest, Union) { - const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); - const set set2(std::set({2, 5, 7, 10, 15, 17})); - const auto& combined = set1.union_with(set2); - EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); + const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); + const set set2(std::set({2, 5, 7, 10, 15, 17})); + const auto& combined = set1.union_with(set2); + EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); } TEST(SetTest, UnionStdSet) { - const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); - const std::set set2({2, 5, 7, 10, 15, 17}); - const auto& combined = set1.union_with(set2); - EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); + const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); + const std::set set2({2, 5, 7, 10, 15, 17}); + const auto& combined = set1.union_with(set2); + EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); } TEST(SetTest, UnionFunctionalSet) { - const set set1({1, 2, 3, 5, 7, 8, 10}); - const set set2({2, 5, 7, 10, 15, 17}); - const auto& combined = set1.union_with(set2); - EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); + const set set1({1, 2, 3, 5, 7, 8, 10}); + const set set2({2, 5, 7, 10, 15, 17}); + const auto& combined = set1.union_with(set2); + EXPECT_EQ(set({1, 2, 3, 5, 7, 8, 10, 15, 17}), combined); } TEST(SetTest, UnionFunctionalSetCustomType) { - const set set1({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); - - const set set2({ - person(51, "George"), - person(81, "Jackie"), - }); - - const auto& combined = set1.union_with(set2); - - const set expected({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate"), - person(51, "George"), - person(81, "Jackie"), - }); - - EXPECT_EQ(expected, combined); + const set set1({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + const set set2({ + person(51, "George"), + person(81, "Jackie"), + }); + + const auto& combined = set1.union_with(set2); + + const set expected({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate"), + person(51, "George"), + person(81, "Jackie"), + }); + + EXPECT_EQ(expected, combined); } TEST(SetTest, Intersection) { - const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); - const set set2(std::set({2, 5, 7, 10, 15, 17})); - const auto& intersection = set1.intersect_with(set2); - EXPECT_EQ(set({2, 5, 7, 10}), intersection); + const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); + const set set2(std::set({2, 5, 7, 10, 15, 17})); + const auto& intersection = set1.intersect_with(set2); + EXPECT_EQ(set({2, 5, 7, 10}), intersection); } TEST(SetTest, IntersectionStdSet) { - const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); - const std::set set2({2, 5, 7, 10, 15, 17}); - const auto& intersection = set1.intersect_with(set2); - EXPECT_EQ(set({2, 5, 7, 10}), intersection); + const set set1(std::set({1, 2, 3, 5, 7, 8, 10})); + const std::set set2({2, 5, 7, 10, 15, 17}); + const auto& intersection = set1.intersect_with(set2); + EXPECT_EQ(set({2, 5, 7, 10}), intersection); } TEST(SetTest, IntersectionFunctionalSet) { - const set set1({1, 2, 3, 5, 7, 8, 10}); - const set set2({2, 5, 7, 10, 15, 17}); - const auto& intersection = set1.intersect_with(set2); - EXPECT_EQ(set({2, 5, 7, 10}), intersection); + const set set1({1, 2, 3, 5, 7, 8, 10}); + const set set2({2, 5, 7, 10, 15, 17}); + const auto& intersection = set1.intersect_with(set2); + EXPECT_EQ(set({2, 5, 7, 10}), intersection); } TEST(SetTest, IntersectionFunctionalSetCustomType) { - const set set1({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate"), - person(51, "George"), - person(81, "Jackie"), - }); - - const set set2({ - person(39, "Robert"), - person(18, "Jannet"), - person(25, "Kate"), - person(52, "Anna"), - person(63, "Simon"), - }); - - const auto& intersection = set1.intersect_with(set2); - - const set expected({ - person(18, "Jannet"), - person(25, "Kate"), - }); - - EXPECT_EQ(expected, intersection); + const set set1({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate"), + person(51, "George"), + person(81, "Jackie"), + }); + + const set set2({ + person(39, "Robert"), + person(18, "Jannet"), + person(25, "Kate"), + person(52, "Anna"), + person(63, "Simon"), + }); + + const auto& intersection = set1.intersect_with(set2); + + const set expected({ + person(18, "Jannet"), + person(25, "Kate"), + }); + + EXPECT_EQ(expected, intersection); } TEST(SetTest, Min) { - const set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto minimum = numbers.min(); - EXPECT_TRUE(minimum.has_value()); - EXPECT_EQ(1, minimum.value()); + const set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto minimum = numbers.min(); + EXPECT_TRUE(minimum.has_value()); + EXPECT_EQ(1, minimum.value()); } TEST(SetTest, MinCustomType) { - const set persons({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate"), - person(62, "Bob") - }); - const auto minimum = persons.min(); + const set persons({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate"), + person(62, "Bob") + }); + const auto minimum = persons.min(); #if defined(__clang__) EXPECT_EQ(person(18, "Jannet"), minimum.value()); #else - EXPECT_EQ(person(62, "Bob"), minimum.value()); + EXPECT_EQ(person(62, "Bob"), minimum.value()); #endif } TEST(SetTest, MinEmptySet) { - const set numbers; - const auto minimum = numbers.min(); - EXPECT_FALSE(minimum.has_value()); + const set numbers; + const auto minimum = numbers.min(); + EXPECT_FALSE(minimum.has_value()); } TEST(SetTest, Max) { - const set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto maximum = numbers.max(); - EXPECT_TRUE(maximum.has_value()); - EXPECT_EQ(8, maximum.value()); + const set numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto maximum = numbers.max(); + EXPECT_TRUE(maximum.has_value()); + EXPECT_EQ(8, maximum.value()); } TEST(SetTest, MaxCustomType) { - const set persons({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate"), - person(62, "Bob") - }); - const auto maximum = persons.max(); - std::cout << maximum.value().name << std::endl; + const set persons({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate"), + person(62, "Bob") + }); + const auto maximum = persons.max(); + std::cout << maximum.value().name << std::endl; #if __linux__ // NOLINT(clang-diagnostic-undef) EXPECT_EQ(person(18, "Jannet"), maximum.value()); #else - EXPECT_EQ(person(25, "Kate"), maximum.value()); + EXPECT_EQ(person(25, "Kate"), maximum.value()); #endif } TEST(SetTest, MaxEmptySet) { - const set numbers; - const auto maximum = numbers.max(); - EXPECT_FALSE(maximum.has_value()); + const set numbers; + const auto maximum = numbers.max(); + EXPECT_FALSE(maximum.has_value()); } TEST(SetTest, Map) { - const set numbers({4, 1, 3}); - const auto mapped_set = numbers.map([](const int& age){ - return child(age); - }); - EXPECT_EQ(3, mapped_set.size()); - EXPECT_EQ(1, mapped_set[0].age); - EXPECT_EQ(3, mapped_set[1].age); - EXPECT_EQ(4, mapped_set[2].age); + const set numbers({4, 1, 3}); + const auto mapped_set = numbers.map([](const int& age) { + return child(age); + }); + EXPECT_EQ(3, mapped_set.size()); + EXPECT_EQ(1, mapped_set[0].age); + EXPECT_EQ(3, mapped_set[1].age); + EXPECT_EQ(4, mapped_set[2].age); } TEST(SetTest, AllOf) { - const set numbers({1, 4, 2, 5, 8, 3}); - EXPECT_TRUE(numbers.all_of([](const int &number) { return number < 10; })); - EXPECT_FALSE(numbers.all_of([](const int &number) { return number > 2; })); + const set numbers({1, 4, 2, 5, 8, 3}); + EXPECT_TRUE(numbers.all_of([](const int &number) { return number < 10; })); + EXPECT_FALSE(numbers.all_of([](const int &number) { return number > 2; })); } TEST(SetTest, AnyOf) { - const set numbers({1, 4, 2, 5, 8, 3}); - EXPECT_TRUE(numbers.any_of([](const int &number) { return number < 5; })); - EXPECT_FALSE(numbers.any_of([](const int &number) { return number > 10; })); + const set numbers({1, 4, 2, 5, 8, 3}); + EXPECT_TRUE(numbers.any_of([](const int &number) { return number < 5; })); + EXPECT_FALSE(numbers.any_of([](const int &number) { return number > 10; })); } TEST(SetTest, NoneOf) { - const set numbers({1, 4, 2, 5, 8, 3}); - EXPECT_TRUE(numbers.none_of([](const int &number) { return number > 10; })); - EXPECT_FALSE(numbers.none_of([](const int &number) { return number < 6; })); + const set numbers({1, 4, 2, 5, 8, 3}); + EXPECT_TRUE(numbers.none_of([](const int &number) { return number > 10; })); + EXPECT_FALSE(numbers.none_of([](const int &number) { return number < 6; })); } TEST(SetTest, Reduce) { - const set tokens({"the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog"}); - const auto sentence = tokens.reduce(std::string(""), [](const std::string& partial, const std::string& token){ - return partial.length() != 0 - ? partial + " " + token - : token; - }); - EXPECT_EQ("brown dog fox jumps lazy over quick the", sentence); + const set tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog" }); + const auto sentence = tokens.reduce(std::string(""), [](const std::string& partial, const std::string& token) { + return partial.length() != 0 + ? partial + " " + token + : token; + }); + EXPECT_EQ("brown dog fox jumps lazy over quick the", sentence); } TEST(SetTest, Filter) { - set numbers({1, 3, -5, 2, -1, 9, -4}); - numbers.filter([](const int& element){ - return element >= 1.5; - }); - EXPECT_EQ(set({2, 3, 9}), numbers); + set numbers({ 1, 3, -5, 2, -1, 9, -4 }); + numbers.filter([](const int& element) { + return element >= 1.5; + }); + EXPECT_EQ(set({2, 3, 9}), numbers); } TEST(SetTest, Filtered) { - const set numbers({1, 3, -5, 2, -1, 9, -4}); - auto filtered_numbers = numbers.filtered([](const int& element){ - return element >= 1.5; - }); - EXPECT_EQ(set({2, 3, 9}), filtered_numbers); - EXPECT_EQ(set({ 1, 3, -5, 2, -1, 9, -4 }), numbers); + const set numbers({ 1, 3, -5, 2, -1, 9, -4 }); + auto filtered_numbers = numbers.filtered([](const int& element) { + return element >= 1.5; + }); + EXPECT_EQ(set({2, 3, 9}), filtered_numbers); + EXPECT_EQ(set({ 1, 3, -5, 2, -1, 9, -4 }), numbers); } TEST(SetTest, ZipWithFunctionalSet) { - const set ages({25, 45, 30, 63}); - const set persons({"Jake", "Bob", "Michael", "Philipp"}); - const auto zipped = ages.zip(persons); - const auto expected = set>({ - std::pair(25, "Bob"), - std::pair(30, "Jake"), - std::pair(45, "Michael"), - std::pair(63, "Philipp"), - }); - EXPECT_EQ(expected, zipped); + const set ages({ 25, 45, 30, 63 }); + const set persons({ "Jake", "Bob", "Michael", "Philipp" }); + const auto zipped = ages.zip(persons); + const auto expected = set>({ + std::pair(25, "Bob"), + std::pair(30, "Jake"), + std::pair(45, "Michael"), + std::pair(63, "Philipp"), + }); + EXPECT_EQ(expected, zipped); } TEST(SetTest, ZipWithFunctionalSetDifferentSizes) { - const set ages({25, 45, 30, 63}); - const set persons({"Jake"}); - EXPECT_DEATH(ages.zip(persons), ""); + const set ages({ 25, 45, 30, 63 }); + const set persons({ "Jake" }); + EXPECT_DEATH(ages.zip(persons), ""); } TEST(SetTest, ZipWithStdSet) { - const set ages({25, 45, 30, 63}); - const std::set persons({"Jake", "Bob", "Michael", "Philipp"}); - const auto zipped = ages.zip(persons); - const auto expected = set>({ - std::pair(25, "Bob"), - std::pair(30, "Jake"), - std::pair(45, "Michael"), - std::pair(63, "Philipp"), - }); - EXPECT_EQ(expected, zipped); + const set ages({ 25, 45, 30, 63 }); + const std::set persons({ "Jake", "Bob", "Michael", "Philipp" }); + const auto zipped = ages.zip(persons); + const auto expected = set>({ + std::pair(25, "Bob"), + std::pair(30, "Jake"), + std::pair(45, "Michael"), + std::pair(63, "Philipp"), + }); + EXPECT_EQ(expected, zipped); } TEST(SetTest, ZipWithStdSetDifferentSizes) { - const set ages({25, 45, 30, 63}); - const std::set persons({"Jake"}); - EXPECT_DEATH(ages.zip(persons), ""); + const set ages({ 25, 45, 30, 63 }); + const std::set persons({ "Jake" }); + EXPECT_DEATH(ages.zip(persons), ""); } TEST(SetTest, ZipWithFunctionalVector) { - const set ages({25, 45, 30, 63}); - const vector persons({"Jake", "Bob", "Michael", "Philipp"}); - const auto zipped = ages.zip(persons); - const auto expected = set>({ - std::pair(25, "Bob"), - std::pair(30, "Jake"), - std::pair(45, "Michael"), - std::pair(63, "Philipp"), - }); - EXPECT_EQ(expected, zipped); + const set ages({ 25, 45, 30, 63 }); + const vector persons({ "Jake", "Bob", "Michael", "Philipp" }); + const auto zipped = ages.zip(persons); + const auto expected = set>({ + std::pair(25, "Bob"), + std::pair(30, "Jake"), + std::pair(45, "Michael"), + std::pair(63, "Philipp"), + }); + EXPECT_EQ(expected, zipped); } TEST(SetTest, ZipWithFunctionalVectorDifferentSizes) { - const set ages({25, 45, 30, 63}); - const vector persons({"Jake"}); - EXPECT_DEATH(ages.zip(persons), ""); + const set ages({ 25, 45, 30, 63 }); + const vector persons({ "Jake" }); + EXPECT_DEATH(ages.zip(persons), ""); } TEST(SetTest, ZipWithStdVector) { - const set ages({25, 45, 30, 63}); - const std::vector persons({"Jake", "Bob", "Michael", "Philipp"}); - const auto zipped = ages.zip(persons); - const auto expected = set>({ - std::pair(25, "Bob"), - std::pair(30, "Jake"), - std::pair(45, "Michael"), - std::pair(63, "Philipp"), - }); - EXPECT_EQ(expected, zipped); + const set ages({ 25, 45, 30, 63 }); + const std::vector persons({ "Jake", "Bob", "Michael", "Philipp" }); + const auto zipped = ages.zip(persons); + const auto expected = set>({ + std::pair(25, "Bob"), + std::pair(30, "Jake"), + std::pair(45, "Michael"), + std::pair(63, "Philipp"), + }); + EXPECT_EQ(expected, zipped); } TEST(SetTest, ZipWithStdVectorDifferentSizes) { - const set ages({25, 45, 30, 63}); - const std::vector persons({"Jake"}); - EXPECT_DEATH(ages.zip(persons), ""); + const set ages({ 25, 45, 30, 63 }); + const std::vector persons({ "Jake" }); + EXPECT_DEATH(ages.zip(persons), ""); } TEST(SetTest, Keys) { - const set numbers({25, 45, 30, 63}); - const auto keys = numbers.keys(); - EXPECT_EQ(vector({25, 30, 45, 63}), keys); + const set numbers({ 25, 45, 30, 63 }); + const auto keys = numbers.keys(); + EXPECT_EQ(vector({25, 30, 45, 63}), keys); } TEST(SetTest, RemoveExistingElement) { - set numbers({1, 4, 2}); - numbers.remove(4); - EXPECT_EQ(set({1, 2}), numbers); + set numbers({1, 4, 2}); + numbers.remove(4); + EXPECT_EQ(set({1, 2}), numbers); } TEST(SetTest, RemoveNonExistentElement) { - set numbers({1, 4, 2}); - numbers.remove(18); - EXPECT_EQ(set({1, 2, 4}), numbers); + set numbers({1, 4, 2}); + numbers.remove(18); + EXPECT_EQ(set({1, 2, 4}), numbers); } TEST(SetTest, RemovingExistingElement) { - const set numbers({1, 4, 2}); - const auto less_numbers = numbers.removing(4); - EXPECT_EQ(set({1, 2}), less_numbers); - EXPECT_EQ(set({1, 2, 4}), numbers); + const set numbers({1, 4, 2}); + const auto less_numbers = numbers.removing(4); + EXPECT_EQ(set({1, 2}), less_numbers); + EXPECT_EQ(set({1, 2, 4}), numbers); } TEST(SetTest, InsertNewElement) { - set numbers({1, 4, 2}); - numbers.insert(18); - EXPECT_EQ(set({1, 2, 4, 18}), numbers); + set numbers({1, 4, 2}); + numbers.insert(18); + EXPECT_EQ(set({1, 2, 4, 18}), numbers); } TEST(SetTest, InsertingNewElement) { - const set numbers({1, 4, 2}); - const auto augmented_numbers = numbers.inserting(18); - EXPECT_EQ(set({1, 2, 4, 18}), augmented_numbers); - EXPECT_EQ(set({1, 2, 4}), numbers); + const set numbers({1, 4, 2}); + const auto augmented_numbers = numbers.inserting(18); + EXPECT_EQ(set({1, 2, 4, 18}), augmented_numbers); + EXPECT_EQ(set({1, 2, 4}), numbers); } TEST(SetTest, InsertExistingElement) { - set numbers({1, 4, 2}); - numbers.insert(2); - EXPECT_EQ(set({1, 2, 4}), numbers); + set numbers({1, 4, 2}); + numbers.insert(2); + EXPECT_EQ(set({1, 2, 4}), numbers); } TEST(SetTest, InsertingExistingElement) { - const set numbers({1, 4, 2}); - const auto augmented_numbers = numbers.inserting(2); - EXPECT_EQ(set({1, 2, 4}), augmented_numbers); - EXPECT_EQ(set({1, 2, 4}), numbers); + const set numbers({1, 4, 2}); + const auto augmented_numbers = numbers.inserting(2); + EXPECT_EQ(set({1, 2, 4}), augmented_numbers); + EXPECT_EQ(set({1, 2, 4}), numbers); } TEST(SetTest, Clear) { - set numbers({1, 4, 2}); - numbers.clear(); - EXPECT_EQ(0, numbers.size()); + set numbers({1, 4, 2}); + numbers.clear(); + EXPECT_EQ(0, numbers.size()); } TEST(SetTest, Clearing) { - const set numbers({1, 4, 2}); - const auto cleared_numbers = numbers.clearing(); - EXPECT_EQ(0, cleared_numbers.size()); - EXPECT_EQ(3, numbers.size()); + const set numbers({1, 4, 2}); + const auto cleared_numbers = numbers.clearing(); + EXPECT_EQ(0, cleared_numbers.size()); + EXPECT_EQ(3, numbers.size()); } TEST(SetTest, IsEmpty) { - const set numbers({1, 4, 2}); - EXPECT_FALSE(numbers.is_empty()); - EXPECT_TRUE(set().is_empty()); + const set numbers({1, 4, 2}); + EXPECT_FALSE(numbers.is_empty()); + EXPECT_TRUE(set().is_empty()); } TEST(SetTest, Contains) { - const set numbers({1, 4, 2}); - EXPECT_TRUE(numbers.contains(1)); - EXPECT_FALSE(numbers.contains(15)); + const set numbers({1, 4, 2}); + EXPECT_TRUE(numbers.contains(1)); + EXPECT_FALSE(numbers.contains(15)); } TEST(SetTest, EqualityOperator) { - const set set1(std::set({1, 2, 3})); - const set set2(std::set({1, 2, 3, 2, 3})); - EXPECT_TRUE(set1 == set2); - EXPECT_FALSE(set1 != set2); + const set set1(std::set({1, 2, 3})); + const set set2(std::set({1, 2, 3, 2, 3})); + EXPECT_TRUE(set1 == set2); + EXPECT_FALSE(set1 != set2); } TEST(SetTest, InequalityOperator) { - const set set1(std::set({1, 2, 3})); - const set set2(std::set({1, 2, 3, 4})); - EXPECT_FALSE(set1 == set2); - EXPECT_TRUE(set1 != set2); + const set set1(std::set({1, 2, 3})); + const set set2(std::set({1, 2, 3, 4})); + EXPECT_FALSE(set1 == set2); + EXPECT_TRUE(set1 != set2); } TEST(SetTest, EqualityOperatorCustomType) { - const set set1({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); - - const set set2({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); - - EXPECT_TRUE(set1 == set2); - EXPECT_FALSE(set1 != set2); + const set set1({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + const set set2({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + EXPECT_TRUE(set1 == set2); + EXPECT_FALSE(set1 != set2); } diff --git a/tests/vector_test.cc b/tests/vector_test.cc index ad74c12..048cfe7 100644 --- a/tests/vector_test.cc +++ b/tests/vector_test.cc @@ -21,1358 +21,1356 @@ // SOFTWARE. #include +#include #include "vector.h" #include "set.h" #include "index_range.h" #include "test_types.h" #include "warnings.h" -#pragma warning( push ) -#pragma warning( disable : 4245) - using namespace fcpp; template void debug(const vector& vec) { - vec.for_each([](const T& element){ - std::cout << element << std::endl; - }); + vec.for_each([](const T& element) { + std::cout << element << std::endl; + }); } TEST(VectorTest, InsertBack) { - vector vector_under_test; - EXPECT_EQ(0, vector_under_test.size()); - - vector_under_test.insert_back(5); - EXPECT_EQ(1, vector_under_test.size()); - EXPECT_EQ(5, vector_under_test[0]); - - vector_under_test.insert_back(-1); - EXPECT_EQ(2, vector_under_test.size()); - EXPECT_EQ(5, vector_under_test[0]); - EXPECT_EQ(-1, vector_under_test[1]); + vector vector_under_test; + EXPECT_EQ(0, vector_under_test.size()); + + vector_under_test.insert_back(5); + EXPECT_EQ(1, vector_under_test.size()); + EXPECT_EQ(5, vector_under_test[0]); + + vector_under_test.insert_back(-1); + EXPECT_EQ(2, vector_under_test.size()); + EXPECT_EQ(5, vector_under_test[0]); + EXPECT_EQ(-1, vector_under_test[1]); } TEST(VectorTest, InsertFront) { - vector vector_under_test; - EXPECT_EQ(0, vector_under_test.size()); - - vector_under_test.insert_front(5); - EXPECT_EQ(1, vector_under_test.size()); - EXPECT_EQ(5, vector_under_test[0]); - - vector_under_test.insert_front(-1); - EXPECT_EQ(2, vector_under_test.size()); - EXPECT_EQ(-1, vector_under_test[0]); - EXPECT_EQ(5, vector_under_test[1]); + vector vector_under_test; + EXPECT_EQ(0, vector_under_test.size()); + + vector_under_test.insert_front(5); + EXPECT_EQ(1, vector_under_test.size()); + EXPECT_EQ(5, vector_under_test[0]); + + vector_under_test.insert_front(-1); + EXPECT_EQ(2, vector_under_test.size()); + EXPECT_EQ(-1, vector_under_test[0]); + EXPECT_EQ(5, vector_under_test[1]); } TEST(VectorTest, InsertingBack) { - const vector vector_under_test({3, 6, 2, 8}); - const auto vector_new_instance = vector_under_test.inserting_back(5); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(3, vector_under_test[0]); - EXPECT_EQ(8, vector_under_test[3]); - EXPECT_EQ(vector({ 3, 6, 2, 8, 5 }), vector_new_instance); + const vector vector_under_test({3, 6, 2, 8}); + const auto vector_new_instance = vector_under_test.inserting_back(5); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(3, vector_under_test[0]); + EXPECT_EQ(8, vector_under_test[3]); + EXPECT_EQ(vector({ 3, 6, 2, 8, 5 }), vector_new_instance); } TEST(VectorTest, InsertingFront) { - const vector vector_under_test({3, 6, 2, 8}); - const auto vector_new_instance = vector_under_test.inserting_front(5); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(3, vector_under_test[0]); - EXPECT_EQ(8, vector_under_test[3]); - EXPECT_EQ(vector({ 5, 3, 6, 2, 8}), vector_new_instance); + const vector vector_under_test({3, 6, 2, 8}); + const auto vector_new_instance = vector_under_test.inserting_front(5); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(3, vector_under_test[0]); + EXPECT_EQ(8, vector_under_test[3]); + EXPECT_EQ(vector({ 5, 3, 6, 2, 8}), vector_new_instance); } TEST(VectorTest, InsertBackFromFunctionalVector) { - vector vector_under_test({4, 5, 6}); - vector_under_test.insert_back(vector({1, 2, 3})); - EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); + vector vector_under_test({ 4, 5, 6 }); + vector_under_test.insert_back(vector({1, 2, 3})); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); } TEST(VectorTest, InsertBackFromStdVector) { - vector vector_under_test({4, 5, 6}); - vector_under_test.insert_back(std::vector{1, 2, 3}); - EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); + vector vector_under_test({ 4, 5, 6 }); + vector_under_test.insert_back(std::vector{ 1, 2, 3 }); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); } TEST(VectorTest, InsertBackFromInitializerList) { - vector vector_under_test({4, 5, 6}); - vector_under_test.insert_back(std::initializer_list{1, 2, 3}); - EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); + vector vector_under_test({ 4, 5, 6 }); + vector_under_test.insert_back(std::initializer_list{ 1, 2, 3 }); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); } TEST(VectorTest, InsertFrontFromFunctionalVector) { - vector vector_under_test({4, 5, 6}); - vector_under_test.insert_front(vector({1, 2, 3})); - EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); + vector vector_under_test({ 4, 5, 6 }); + vector_under_test.insert_front(vector({1, 2, 3})); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); } TEST(VectorTest, InsertFrontFromStdVector) { - vector vector_under_test({4, 5, 6}); - vector_under_test.insert_front(std::vector{1, 2, 3}); - EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); + vector vector_under_test({ 4, 5, 6 }); + vector_under_test.insert_front(std::vector{ 1, 2, 3 }); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); } TEST(VectorTest, InsertFrontFromInitializerList) { - vector vector_under_test({4, 5, 6}); - vector_under_test.insert_front(std::initializer_list{1, 2, 3}); - EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); + vector vector_under_test({ 4, 5, 6 }); + vector_under_test.insert_front(std::initializer_list{ 1, 2, 3 }); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); } TEST(VectorTest, InsertingBackFromFunctionalVector) { - const vector vector_under_test({4, 5, 6}); - const auto vector_new_instance = vector_under_test.inserting_back(vector({1, 2, 3})); - EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); + const vector vector_under_test({ 4, 5, 6 }); + const auto vector_new_instance = vector_under_test.inserting_back(vector({1, 2, 3})); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); } TEST(VectorTest, InsertingBackFromStdVector) { - const vector vector_under_test({4, 5, 6}); - const auto vector_new_instance = vector_under_test.inserting_back(std::vector{1, 2, 3}); - EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); + const vector vector_under_test({ 4, 5, 6 }); + const auto vector_new_instance = vector_under_test.inserting_back(std::vector{ 1, 2, 3 }); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); } TEST(VectorTest, InsertingBackFromInitializerList) { - const vector vector_under_test({4, 5, 6}); - const auto vector_new_instance = vector_under_test.inserting_back(std::initializer_list{1, 2, 3}); - EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); + const vector vector_under_test({ 4, 5, 6 }); + const auto vector_new_instance = vector_under_test.inserting_back(std::initializer_list{ 1, 2, 3 }); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); } TEST(VectorTest, InsertingFrontFromFunctionalVector) { - const vector vector_under_test({4, 5, 6}); - const auto vector_new_instance = vector_under_test.inserting_front(vector({1, 2, 3})); - EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); + const vector vector_under_test({ 4, 5, 6 }); + const auto vector_new_instance = vector_under_test.inserting_front(vector({1, 2, 3})); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); } TEST(VectorTest, InsertingFrontFromStdVector) { - const vector vector_under_test({4, 5, 6}); - const auto vector_new_instance = vector_under_test.inserting_front(std::vector{1, 2, 3}); - EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); + const vector vector_under_test({ 4, 5, 6 }); + const auto vector_new_instance = vector_under_test.inserting_front(std::vector{ 1, 2, 3 }); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); } TEST(VectorTest, InsertingFrontFromInitializerList) { - const vector vector_under_test({4, 5, 6}); - const auto vector_new_instance = vector_under_test.inserting_front(std::initializer_list{1, 2, 3}); - EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); + const vector vector_under_test({ 4, 5, 6 }); + const auto vector_new_instance = vector_under_test.inserting_front(std::initializer_list{ 1, 2, 3 }); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); } TEST(VectorTest, Map) { - const vector vector_under_test({1, 3, 4}); - const auto mapped_vector = vector_under_test.map([](const int& age){ - return child(age); - }); - EXPECT_EQ(3, mapped_vector.size()); - EXPECT_EQ(1, mapped_vector[0].age); - EXPECT_EQ(3, mapped_vector[1].age); - EXPECT_EQ(4, mapped_vector[2].age); + const vector vector_under_test({1, 3, 4}); + const auto mapped_vector = vector_under_test.map([](const int& age) { + return child(age); + }); + EXPECT_EQ(3, mapped_vector.size()); + EXPECT_EQ(1, mapped_vector[0].age); + EXPECT_EQ(3, mapped_vector[1].age); + EXPECT_EQ(4, mapped_vector[2].age); } #ifdef PARALLEL_ALGORITHM_AVAILABLE TEST(VectorTest, MapParallel) { - const vector vector_under_test({1, 3, 4}); - const auto mapped_vector = vector_under_test.map_parallel([](const int& age){ - return child(age); - }); - EXPECT_EQ(3, mapped_vector.size()); - EXPECT_EQ(1, mapped_vector[0].age); - EXPECT_EQ(3, mapped_vector[1].age); - EXPECT_EQ(4, mapped_vector[2].age); + const vector vector_under_test({1, 3, 4}); + const auto mapped_vector = vector_under_test.map_parallel([](const int& age) { + return child(age); + }); + EXPECT_EQ(3, mapped_vector.size()); + EXPECT_EQ(1, mapped_vector[0].age); + EXPECT_EQ(3, mapped_vector[1].age); + EXPECT_EQ(4, mapped_vector[2].age); } #endif TEST(VectorTest, Filter) { - vector vector_under_test({child(1), child(3), child(4)}); - vector_under_test.filter([](const child& child){ - return child.age < 2; - }); - EXPECT_EQ(1, vector_under_test.size()); - EXPECT_EQ(1, vector_under_test[0].age); - vector_under_test.filter([](const child& child){ - return child.age > 7; - }); - EXPECT_EQ(0, vector_under_test.size()); + vector vector_under_test({child(1), child(3), child(4)}); + vector_under_test.filter([](const child& child) { + return child.age < 2; + }); + EXPECT_EQ(1, vector_under_test.size()); + EXPECT_EQ(1, vector_under_test[0].age); + vector_under_test.filter([](const child& child) { + return child.age > 7; + }); + EXPECT_EQ(0, vector_under_test.size()); } #ifdef PARALLEL_ALGORITHM_AVAILABLE TEST(VectorTest, FilterParallel) { - vector vector_under_test({child(1), child(3), child(4)}); - vector_under_test.filter_parallel([](const child& child){ - return child.age < 2; - }); - EXPECT_EQ(1, vector_under_test.size()); - EXPECT_EQ(1, vector_under_test[0].age); - vector_under_test.filter_parallel([](const child& child){ - return child.age > 7; - }); - EXPECT_EQ(0, vector_under_test.size()); + vector vector_under_test({child(1), child(3), child(4)}); + vector_under_test.filter_parallel([](const child& child) { + return child.age < 2; + }); + EXPECT_EQ(1, vector_under_test.size()); + EXPECT_EQ(1, vector_under_test[0].age); + vector_under_test.filter_parallel([](const child& child) { + return child.age > 7; + }); + EXPECT_EQ(0, vector_under_test.size()); } #endif TEST(VectorTest, Filtered) { - const vector vector_under_test({child(1), child(3), child(4)}); - const auto filtered_vector = vector_under_test.filtered([](const child& child){ - return child.age < 2; - }); - EXPECT_EQ(3, vector_under_test.size()); - EXPECT_EQ(1, filtered_vector.size()); - EXPECT_EQ(1, filtered_vector[0].age); + const vector vector_under_test({child(1), child(3), child(4)}); + const auto filtered_vector = vector_under_test.filtered([](const child& child) { + return child.age < 2; + }); + EXPECT_EQ(3, vector_under_test.size()); + EXPECT_EQ(1, filtered_vector.size()); + EXPECT_EQ(1, filtered_vector[0].age); } #ifdef PARALLEL_ALGORITHM_AVAILABLE TEST(VectorTest, FilteredParallel) { - const vector vector_under_test({child(1), child(3), child(4)}); - const auto filtered_vector = vector_under_test.filtered_parallel([](const child& child){ - return child.age < 2; - }); - EXPECT_EQ(3, vector_under_test.size()); - EXPECT_EQ(1, filtered_vector.size()); - EXPECT_EQ(1, filtered_vector[0].age); + const vector vector_under_test({child(1), child(3), child(4)}); + const auto filtered_vector = vector_under_test.filtered_parallel([](const child& child) { + return child.age < 2; + }); + EXPECT_EQ(3, vector_under_test.size()); + EXPECT_EQ(1, filtered_vector.size()); + EXPECT_EQ(1, filtered_vector[0].age); } #endif TEST(VectorTest, Reduce) { - const vector vector_under_test({child(1), child(3), child(4)}); + const vector vector_under_test({ child(1), child(3), child(4) }); const auto age_sum = vector_under_test.reduce(0, [](const int& partial_sum, const child& child){ - return partial_sum + child.age; - }); - EXPECT_EQ(8, age_sum); + return partial_sum + child.age; + }); + EXPECT_EQ(8, age_sum); } TEST(VectorTest, ReduceString) { - const vector tokens({"the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog"}); - const auto sentence = tokens.reduce(std::string(""), [](const std::string& partial, const std::string& token){ - return partial.length() != 0 - ? partial + " " + token - : token; - }); - EXPECT_EQ("the quick brown fox jumps over the lazy brown dog", sentence); + const vector tokens({ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "brown", "dog"}); + const auto sentence = tokens.reduce(std::string(""), [](const std::string& partial, const std::string& token) { + return partial.length() != 0 + ? partial + " " + token + : token; + }); + EXPECT_EQ("the quick brown fox jumps over the lazy brown dog", sentence); } TEST(VectorTest, Reverse) { - vector vector_under_test({child(6), child(2), child(9)}); - vector_under_test.reverse(); - EXPECT_EQ(3, vector_under_test.size()); - EXPECT_EQ(9, vector_under_test[0].age); - EXPECT_EQ(2, vector_under_test[1].age); - EXPECT_EQ(6, vector_under_test[2].age); + vector vector_under_test({child(6), child(2), child(9)}); + vector_under_test.reverse(); + EXPECT_EQ(3, vector_under_test.size()); + EXPECT_EQ(9, vector_under_test[0].age); + EXPECT_EQ(2, vector_under_test[1].age); + EXPECT_EQ(6, vector_under_test[2].age); } TEST(VectorTest, Reversed) { - const vector vector_under_test({child(6), child(2), child(9)}); - const auto reversed_vector = vector_under_test.reversed(); - EXPECT_EQ(3, reversed_vector.size()); - EXPECT_EQ(9, reversed_vector[0].age); - EXPECT_EQ(2, reversed_vector[1].age); - EXPECT_EQ(6, reversed_vector[2].age); - - EXPECT_EQ(3, vector_under_test.size()); - EXPECT_EQ(6, vector_under_test[0].age); - EXPECT_EQ(2, vector_under_test[1].age); - EXPECT_EQ(9, vector_under_test[2].age); + const vector vector_under_test({child(6), child(2), child(9)}); + const auto reversed_vector = vector_under_test.reversed(); + EXPECT_EQ(3, reversed_vector.size()); + EXPECT_EQ(9, reversed_vector[0].age); + EXPECT_EQ(2, reversed_vector[1].age); + EXPECT_EQ(6, reversed_vector[2].age); + + EXPECT_EQ(3, vector_under_test.size()); + EXPECT_EQ(6, vector_under_test[0].age); + EXPECT_EQ(2, vector_under_test[1].age); + EXPECT_EQ(9, vector_under_test[2].age); } TEST(VectorTest, ZipWithStdVectorUnequalSizesThrows) { - const vector ages_vector({32, 25, 53, 62}); - EXPECT_DEATH({ const auto zipped_vector = ages_vector.zip(std::vector({"Jake", "Mary"})); }, ""); + const vector ages_vector({32, 25, 53, 62}); + EXPECT_DEATH({ const auto zipped_vector = ages_vector.zip(std::vector({"Jake", "Mary"})); }, ""); } TEST(VectorTest, ZipWithFunctionalVectorUnequalSizesThrows) { - const vector ages_vector({32, 25, 53, 62}); - const auto names_vector = vector({"Jake", "Mary"}); - EXPECT_DEATH({ const auto zipped_vector = ages_vector.zip(names_vector); }, ""); + const vector ages_vector({32, 25, 53, 62}); + const auto names_vector = vector({"Jake", "Mary"}); + EXPECT_DEATH({ const auto zipped_vector = ages_vector.zip(names_vector); }, ""); } TEST(VectorTest, ZipWithFunctionalVector) { - const vector ages_vector({32, 25, 53}); - const vector names_vector({"Jake", "Mary", "John"}); - const auto zipped_vector = ages_vector.zip(names_vector); - EXPECT_EQ(3, zipped_vector.size()); - - EXPECT_EQ(32, zipped_vector[0].first); - EXPECT_EQ("Jake", zipped_vector[0].second); - - EXPECT_EQ(25, zipped_vector[1].first); - EXPECT_EQ("Mary", zipped_vector[1].second); - - EXPECT_EQ(53, zipped_vector[2].first); - EXPECT_EQ("John", zipped_vector[2].second); + const vector ages_vector({32, 25, 53}); + const vector names_vector({"Jake", "Mary", "John"}); + const auto zipped_vector = ages_vector.zip(names_vector); + EXPECT_EQ(3, zipped_vector.size()); + + EXPECT_EQ(32, zipped_vector[0].first); + EXPECT_EQ("Jake", zipped_vector[0].second); + + EXPECT_EQ(25, zipped_vector[1].first); + EXPECT_EQ("Mary", zipped_vector[1].second); + + EXPECT_EQ(53, zipped_vector[2].first); + EXPECT_EQ("John", zipped_vector[2].second); } TEST(VectorTest, ZipWithStdVector) { - const vector ages_vector({32, 25, 53}); - const auto zipped_vector = ages_vector.zip(std::vector{"Jake", "Mary", "John"}); - EXPECT_EQ(3, zipped_vector.size()); - - EXPECT_EQ(32, zipped_vector[0].first); - EXPECT_EQ("Jake", zipped_vector[0].second); - - EXPECT_EQ(25, zipped_vector[1].first); - EXPECT_EQ("Mary", zipped_vector[1].second); - - EXPECT_EQ(53, zipped_vector[2].first); - EXPECT_EQ("John", zipped_vector[2].second); + const vector ages_vector({32, 25, 53}); + const auto zipped_vector = ages_vector.zip(std::vector{"Jake", "Mary", "John"}); + EXPECT_EQ(3, zipped_vector.size()); + + EXPECT_EQ(32, zipped_vector[0].first); + EXPECT_EQ("Jake", zipped_vector[0].second); + + EXPECT_EQ(25, zipped_vector[1].first); + EXPECT_EQ("Mary", zipped_vector[1].second); + + EXPECT_EQ(53, zipped_vector[2].first); + EXPECT_EQ("John", zipped_vector[2].second); } TEST(VectorTest, ZipWithInitializerList) { - const vector ages_vector({32, 25, 53}); - const auto zipped_vector = ages_vector.zip(std::initializer_list{"Jake", "Mary", "John"}); - EXPECT_EQ(3, zipped_vector.size()); - - EXPECT_EQ(32, zipped_vector[0].first); - EXPECT_EQ("Jake", zipped_vector[0].second); - - EXPECT_EQ(25, zipped_vector[1].first); - EXPECT_EQ("Mary", zipped_vector[1].second); - - EXPECT_EQ(53, zipped_vector[2].first); - EXPECT_EQ("John", zipped_vector[2].second); + const vector ages_vector({32, 25, 53}); + const auto zipped_vector = ages_vector.zip(std::initializer_list{"Jake", "Mary", "John"}); + EXPECT_EQ(3, zipped_vector.size()); + + EXPECT_EQ(32, zipped_vector[0].first); + EXPECT_EQ("Jake", zipped_vector[0].second); + + EXPECT_EQ(25, zipped_vector[1].first); + EXPECT_EQ("Mary", zipped_vector[1].second); + + EXPECT_EQ(53, zipped_vector[2].first); + EXPECT_EQ("John", zipped_vector[2].second); } TEST(VectorTest, Sort) { - vector vector_under_test({ - person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") - }); - vector_under_test.sort([](const person& person1, const person& person2){ - return person1.name < person2.name; - }); - EXPECT_EQ(4, vector_under_test.size()); - - EXPECT_EQ("Alice", vector_under_test[0].name); - EXPECT_EQ(8, vector_under_test[0].age); - - EXPECT_EQ("Bob", vector_under_test[1].name); - EXPECT_EQ(34, vector_under_test[1].age); - - EXPECT_EQ("Jake", vector_under_test[2].name); - EXPECT_EQ(45, vector_under_test[2].age); - - EXPECT_EQ("Manfred", vector_under_test[3].name); - EXPECT_EQ(52, vector_under_test[3].age); + vector vector_under_test({ + person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") + }); + vector_under_test.sort([](const person& person1, const person& person2) + { + return person1.name < person2.name; + }); + EXPECT_EQ(4, vector_under_test.size()); + + EXPECT_EQ("Alice", vector_under_test[0].name); + EXPECT_EQ(8, vector_under_test[0].age); + + EXPECT_EQ("Bob", vector_under_test[1].name); + EXPECT_EQ(34, vector_under_test[1].age); + + EXPECT_EQ("Jake", vector_under_test[2].name); + EXPECT_EQ(45, vector_under_test[2].age); + + EXPECT_EQ("Manfred", vector_under_test[3].name); + EXPECT_EQ(52, vector_under_test[3].age); } TEST(VectorTest, Sorted) { - const vector vector_under_test({ - person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") - }); - const auto sorted_vector = vector_under_test.sorted([](const person& person1, const person& person2){ - return person1.name < person2.name; - }); - - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ("Jake", vector_under_test[0].name); - EXPECT_EQ(45, vector_under_test[0].age); - EXPECT_EQ("Bob", vector_under_test[1].name); - EXPECT_EQ(34, vector_under_test[1].age); - EXPECT_EQ("Manfred", vector_under_test[2].name); - EXPECT_EQ(52, vector_under_test[2].age); - EXPECT_EQ("Alice", vector_under_test[3].name); - EXPECT_EQ(8, vector_under_test[3].age); - - EXPECT_EQ(4, sorted_vector.size()); - EXPECT_EQ("Alice", sorted_vector[0].name); - EXPECT_EQ(8, sorted_vector[0].age); - EXPECT_EQ("Bob", sorted_vector[1].name); - EXPECT_EQ(34, sorted_vector[1].age); - EXPECT_EQ("Jake", sorted_vector[2].name); - EXPECT_EQ(45, sorted_vector[2].age); - EXPECT_EQ("Manfred", sorted_vector[3].name); - EXPECT_EQ(52, sorted_vector[3].age); + const vector vector_under_test({ + person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") + }); + const auto sorted_vector = vector_under_test.sorted([](const person& person1, const person& person2) { + return person1.name < person2.name; + }); + + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ("Jake", vector_under_test[0].name); + EXPECT_EQ(45, vector_under_test[0].age); + EXPECT_EQ("Bob", vector_under_test[1].name); + EXPECT_EQ(34, vector_under_test[1].age); + EXPECT_EQ("Manfred", vector_under_test[2].name); + EXPECT_EQ(52, vector_under_test[2].age); + EXPECT_EQ("Alice", vector_under_test[3].name); + EXPECT_EQ(8, vector_under_test[3].age); + + EXPECT_EQ(4, sorted_vector.size()); + EXPECT_EQ("Alice", sorted_vector[0].name); + EXPECT_EQ(8, sorted_vector[0].age); + EXPECT_EQ("Bob", sorted_vector[1].name); + EXPECT_EQ(34, sorted_vector[1].age); + EXPECT_EQ("Jake", sorted_vector[2].name); + EXPECT_EQ(45, sorted_vector[2].age); + EXPECT_EQ("Manfred", sorted_vector[3].name); + EXPECT_EQ(52, sorted_vector[3].age); } TEST(VectorTest, SortAscending) { - vector vector_under_test({3, 1, 9, -4}); - vector_under_test.sort_ascending(); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(-4, vector_under_test[0]); - EXPECT_EQ(1, vector_under_test[1]); - EXPECT_EQ(3, vector_under_test[2]); - EXPECT_EQ(9, vector_under_test[3]); + vector vector_under_test({3, 1, 9, -4}); + vector_under_test.sort_ascending(); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(-4, vector_under_test[0]); + EXPECT_EQ(1, vector_under_test[1]); + EXPECT_EQ(3, vector_under_test[2]); + EXPECT_EQ(9, vector_under_test[3]); } TEST(VectorTest, SortedAscending) { - const vector vector_under_test({3, 1, 9, -4}); - const auto sorted_vector = vector_under_test.sorted_ascending(); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(3, vector_under_test[0]); - EXPECT_EQ(1, vector_under_test[1]); - EXPECT_EQ(9, vector_under_test[2]); - EXPECT_EQ(-4, vector_under_test[3]); - - EXPECT_EQ(4, sorted_vector.size()); - EXPECT_EQ(-4, sorted_vector[0]); - EXPECT_EQ(1, sorted_vector[1]); - EXPECT_EQ(3, sorted_vector[2]); - EXPECT_EQ(9, sorted_vector[3]); + const vector vector_under_test({3, 1, 9, -4}); + const auto sorted_vector = vector_under_test.sorted_ascending(); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(3, vector_under_test[0]); + EXPECT_EQ(1, vector_under_test[1]); + EXPECT_EQ(9, vector_under_test[2]); + EXPECT_EQ(-4, vector_under_test[3]); + + EXPECT_EQ(4, sorted_vector.size()); + EXPECT_EQ(-4, sorted_vector[0]); + EXPECT_EQ(1, sorted_vector[1]); + EXPECT_EQ(3, sorted_vector[2]); + EXPECT_EQ(9, sorted_vector[3]); } TEST(VectorTest, SortDescending) { - vector vector_under_test({3, 1, 9, -4}); - vector_under_test.sort_descending(); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(9, vector_under_test[0]); - EXPECT_EQ(3, vector_under_test[1]); - EXPECT_EQ(1, vector_under_test[2]); - EXPECT_EQ(-4, vector_under_test[3]); + vector vector_under_test({3, 1, 9, -4}); + vector_under_test.sort_descending(); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(9, vector_under_test[0]); + EXPECT_EQ(3, vector_under_test[1]); + EXPECT_EQ(1, vector_under_test[2]); + EXPECT_EQ(-4, vector_under_test[3]); } TEST(VectorTest, SortedDescending) { - const vector vector_under_test({3, 1, 9, -4}); - const auto sorted_vector = vector_under_test.sorted_descending(); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(3, vector_under_test[0]); - EXPECT_EQ(1, vector_under_test[1]); - EXPECT_EQ(9, vector_under_test[2]); - EXPECT_EQ(-4, vector_under_test[3]); - - EXPECT_EQ(4, sorted_vector.size()); - EXPECT_EQ(9, sorted_vector[0]); - EXPECT_EQ(3, sorted_vector[1]); - EXPECT_EQ(1, sorted_vector[2]); - EXPECT_EQ(-4, sorted_vector[3]); + const vector vector_under_test({3, 1, 9, -4}); + const auto sorted_vector = vector_under_test.sorted_descending(); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(3, vector_under_test[0]); + EXPECT_EQ(1, vector_under_test[1]); + EXPECT_EQ(9, vector_under_test[2]); + EXPECT_EQ(-4, vector_under_test[3]); + + EXPECT_EQ(4, sorted_vector.size()); + EXPECT_EQ(9, sorted_vector[0]); + EXPECT_EQ(3, sorted_vector[1]); + EXPECT_EQ(1, sorted_vector[2]); + EXPECT_EQ(-4, sorted_vector[3]); } #ifdef PARALLEL_ALGORITHM_AVAILABLE TEST(VectorTest, SortParallel) { - vector vector_under_test({ - person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") - }); - vector_under_test.sort_parallel([](const person& person1, const person& person2){ - return person1.name < person2.name; - }); - EXPECT_EQ(4, vector_under_test.size()); - - EXPECT_EQ("Alice", vector_under_test[0].name); - EXPECT_EQ(8, vector_under_test[0].age); - - EXPECT_EQ("Bob", vector_under_test[1].name); - EXPECT_EQ(34, vector_under_test[1].age); - - EXPECT_EQ("Jake", vector_under_test[2].name); - EXPECT_EQ(45, vector_under_test[2].age); - - EXPECT_EQ("Manfred", vector_under_test[3].name); - EXPECT_EQ(52, vector_under_test[3].age); + vector vector_under_test({ + person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") + }); + vector_under_test.sort_parallel([](const person& person1, const person& person2){ + return person1.name < person2.name; + }); + EXPECT_EQ(4, vector_under_test.size()); + + EXPECT_EQ("Alice", vector_under_test[0].name); + EXPECT_EQ(8, vector_under_test[0].age); + + EXPECT_EQ("Bob", vector_under_test[1].name); + EXPECT_EQ(34, vector_under_test[1].age); + + EXPECT_EQ("Jake", vector_under_test[2].name); + EXPECT_EQ(45, vector_under_test[2].age); + + EXPECT_EQ("Manfred", vector_under_test[3].name); + EXPECT_EQ(52, vector_under_test[3].age); } TEST(VectorTest, SortedParallel) { - const vector vector_under_test({ - person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") - }); - const auto sorted_vector = vector_under_test.sorted_parallel([](const person& person1, const person& person2){ - return person1.name < person2.name; - }); - - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ("Jake", vector_under_test[0].name); - EXPECT_EQ(45, vector_under_test[0].age); - EXPECT_EQ("Bob", vector_under_test[1].name); - EXPECT_EQ(34, vector_under_test[1].age); - EXPECT_EQ("Manfred", vector_under_test[2].name); - EXPECT_EQ(52, vector_under_test[2].age); - EXPECT_EQ("Alice", vector_under_test[3].name); - EXPECT_EQ(8, vector_under_test[3].age); - - EXPECT_EQ(4, sorted_vector.size()); - EXPECT_EQ("Alice", sorted_vector[0].name); - EXPECT_EQ(8, sorted_vector[0].age); - EXPECT_EQ("Bob", sorted_vector[1].name); - EXPECT_EQ(34, sorted_vector[1].age); - EXPECT_EQ("Jake", sorted_vector[2].name); - EXPECT_EQ(45, sorted_vector[2].age); - EXPECT_EQ("Manfred", sorted_vector[3].name); - EXPECT_EQ(52, sorted_vector[3].age); + const vector vector_under_test({ + person(45, "Jake"), person(34, "Bob"), person(52, "Manfred"), person(8, "Alice") + }); + const auto sorted_vector = vector_under_test.sorted_parallel([](const person& person1, const person& person2){ + return person1.name < person2.name; + }); + + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ("Jake", vector_under_test[0].name); + EXPECT_EQ(45, vector_under_test[0].age); + EXPECT_EQ("Bob", vector_under_test[1].name); + EXPECT_EQ(34, vector_under_test[1].age); + EXPECT_EQ("Manfred", vector_under_test[2].name); + EXPECT_EQ(52, vector_under_test[2].age); + EXPECT_EQ("Alice", vector_under_test[3].name); + EXPECT_EQ(8, vector_under_test[3].age); + + EXPECT_EQ(4, sorted_vector.size()); + EXPECT_EQ("Alice", sorted_vector[0].name); + EXPECT_EQ(8, sorted_vector[0].age); + EXPECT_EQ("Bob", sorted_vector[1].name); + EXPECT_EQ(34, sorted_vector[1].age); + EXPECT_EQ("Jake", sorted_vector[2].name); + EXPECT_EQ(45, sorted_vector[2].age); + EXPECT_EQ("Manfred", sorted_vector[3].name); + EXPECT_EQ(52, sorted_vector[3].age); } TEST(VectorTest, SortAscendingParallel) { - vector vector_under_test({3, 1, 9, -4}); - vector_under_test.sort_ascending_parallel(); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(-4, vector_under_test[0]); - EXPECT_EQ(1, vector_under_test[1]); - EXPECT_EQ(3, vector_under_test[2]); - EXPECT_EQ(9, vector_under_test[3]); + vector vector_under_test({3, 1, 9, -4}); + vector_under_test.sort_ascending_parallel(); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(-4, vector_under_test[0]); + EXPECT_EQ(1, vector_under_test[1]); + EXPECT_EQ(3, vector_under_test[2]); + EXPECT_EQ(9, vector_under_test[3]); } TEST(VectorTest, SortedAscendingParallel) { - const vector vector_under_test({3, 1, 9, -4}); - const auto sorted_vector = vector_under_test.sorted_ascending_parallel(); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(3, vector_under_test[0]); - EXPECT_EQ(1, vector_under_test[1]); - EXPECT_EQ(9, vector_under_test[2]); - EXPECT_EQ(-4, vector_under_test[3]); - - EXPECT_EQ(4, sorted_vector.size()); - EXPECT_EQ(-4, sorted_vector[0]); - EXPECT_EQ(1, sorted_vector[1]); - EXPECT_EQ(3, sorted_vector[2]); - EXPECT_EQ(9, sorted_vector[3]); + const vector vector_under_test({3, 1, 9, -4}); + const auto sorted_vector = vector_under_test.sorted_ascending_parallel(); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(3, vector_under_test[0]); + EXPECT_EQ(1, vector_under_test[1]); + EXPECT_EQ(9, vector_under_test[2]); + EXPECT_EQ(-4, vector_under_test[3]); + + EXPECT_EQ(4, sorted_vector.size()); + EXPECT_EQ(-4, sorted_vector[0]); + EXPECT_EQ(1, sorted_vector[1]); + EXPECT_EQ(3, sorted_vector[2]); + EXPECT_EQ(9, sorted_vector[3]); } TEST(VectorTest, SortDescendingParallel) { - vector vector_under_test({3, 1, 9, -4}); - vector_under_test.sort_descending_parallel(); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(9, vector_under_test[0]); - EXPECT_EQ(3, vector_under_test[1]); - EXPECT_EQ(1, vector_under_test[2]); - EXPECT_EQ(-4, vector_under_test[3]); + vector vector_under_test({3, 1, 9, -4}); + vector_under_test.sort_descending_parallel(); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(9, vector_under_test[0]); + EXPECT_EQ(3, vector_under_test[1]); + EXPECT_EQ(1, vector_under_test[2]); + EXPECT_EQ(-4, vector_under_test[3]); } TEST(VectorTest, SortedDescendingParallel) { - const vector vector_under_test({3, 1, 9, -4}); - const auto sorted_vector = vector_under_test.sorted_descending_parallel(); - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(3, vector_under_test[0]); - EXPECT_EQ(1, vector_under_test[1]); - EXPECT_EQ(9, vector_under_test[2]); - EXPECT_EQ(-4, vector_under_test[3]); - - EXPECT_EQ(4, sorted_vector.size()); - EXPECT_EQ(9, sorted_vector[0]); - EXPECT_EQ(3, sorted_vector[1]); - EXPECT_EQ(1, sorted_vector[2]); - EXPECT_EQ(-4, sorted_vector[3]); + const vector vector_under_test({3, 1, 9, -4}); + const auto sorted_vector = vector_under_test.sorted_descending_parallel(); + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(3, vector_under_test[0]); + EXPECT_EQ(1, vector_under_test[1]); + EXPECT_EQ(9, vector_under_test[2]); + EXPECT_EQ(-4, vector_under_test[3]); + + EXPECT_EQ(4, sorted_vector.size()); + EXPECT_EQ(9, sorted_vector[0]); + EXPECT_EQ(3, sorted_vector[1]); + EXPECT_EQ(1, sorted_vector[2]); + EXPECT_EQ(-4, sorted_vector[3]); } #endif TEST(VectorTest, SubscriptOperatorNegativeDeath) { - const vector vector_under_test({3, 1, 9, -4}); - EXPECT_DEATH(vector_under_test[-1], ""); + const vector vector_under_test({3, 1, 9, -4}); + EXPECT_DEATH(vector_under_test[-1], ""); } TEST(VectorTest, SubscriptOperatorIndexEqualToSizeDeath) { - const vector vector_under_test({3, 1, 9, -4}); - EXPECT_DEATH(vector_under_test[4], ""); + const vector vector_under_test({3, 1, 9, -4}); + EXPECT_DEATH(vector_under_test[4], ""); } TEST(VectorTest, SubscriptOperatorIndexLargerThanSizeDeath) { - const vector vector_under_test({3, 1, 9, -4}); - EXPECT_DEATH(vector_under_test[5], ""); + const vector vector_under_test({3, 1, 9, -4}); + EXPECT_DEATH(vector_under_test[5], ""); } TEST(VectorTest, SubscriptOperatorAssignNegativeDeath) { - vector vector_under_test({3, 1, 9, -4}); - EXPECT_DEATH(vector_under_test[-1] = 5, ""); + vector vector_under_test({3, 1, 9, -4}); + EXPECT_DEATH(vector_under_test[-1] = 5, ""); } TEST(VectorTest, SubscriptOperatorAssignIndexEqualSizeDeath) { - vector vector_under_test({3, 1, 9, -4}); - EXPECT_DEATH(vector_under_test[4] = 5, ""); + vector vector_under_test({3, 1, 9, -4}); + EXPECT_DEATH(vector_under_test[4] = 5, ""); } TEST(VectorTest, SubscriptOperatorAssignIndexLargerThanSizeDeath) { - vector vector_under_test({3, 1, 9, -4}); - EXPECT_DEATH(vector_under_test[5] = -3, ""); + vector vector_under_test({3, 1, 9, -4}); + EXPECT_DEATH(vector_under_test[5] = -3, ""); } TEST(VectorTest, SubscriptOperatorAssign) { - vector vector_under_test({3, 1, 9, -4}); - vector_under_test[2] = 7; - EXPECT_EQ(4, vector_under_test.size()); - EXPECT_EQ(3, vector_under_test[0]); - EXPECT_EQ(1, vector_under_test[1]); - EXPECT_EQ(7, vector_under_test[2]); - EXPECT_EQ(-4, vector_under_test[3]); + vector vector_under_test({3, 1, 9, -4}); + vector_under_test[2] = 7; + EXPECT_EQ(4, vector_under_test.size()); + EXPECT_EQ(3, vector_under_test[0]); + EXPECT_EQ(1, vector_under_test[1]); + EXPECT_EQ(7, vector_under_test[2]); + EXPECT_EQ(-4, vector_under_test[3]); } TEST(VectorTest, FindFirstIndexEmptyVector) { - const vector vector_under_test; - EXPECT_FALSE(vector_under_test.find_first_index(-3).has_value()); + const vector vector_under_test; + EXPECT_FALSE(vector_under_test.find_first_index(-3).has_value()); } TEST(VectorTest, FindFirstIndexFilledVectorWithoutMatch) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_FALSE(vector_under_test.find_first_index(9).has_value()); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_FALSE(vector_under_test.find_first_index(9).has_value()); } TEST(VectorTest, FindFirstIndexFilledVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_EQ(0, vector_under_test.find_first_index(1).value()); - EXPECT_EQ(7, vector_under_test.find_first_index(7).value()); - EXPECT_EQ(3, vector_under_test.find_first_index(5).value()); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_EQ(0, vector_under_test.find_first_index(1).value()); + EXPECT_EQ(7, vector_under_test.find_first_index(7).value()); + EXPECT_EQ(3, vector_under_test.find_first_index(5).value()); } TEST(VectorTest, FindLastIndexEmptyVector) { - const vector vector_under_test; - EXPECT_FALSE(vector_under_test.find_last_index(-3).has_value()); + const vector vector_under_test; + EXPECT_FALSE(vector_under_test.find_last_index(-3).has_value()); } TEST(VectorTest, FindLastIndexFilledVectorWithoutMatch) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_FALSE(vector_under_test.find_last_index(9).has_value()); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_FALSE(vector_under_test.find_last_index(9).has_value()); } TEST(VectorTest, FindLastIndexFilledVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_EQ(8, vector_under_test.find_last_index(1).value()); - EXPECT_EQ(7, vector_under_test.find_last_index(7).value()); - EXPECT_EQ(3, vector_under_test.find_last_index(5).value()); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_EQ(8, vector_under_test.find_last_index(1).value()); + EXPECT_EQ(7, vector_under_test.find_last_index(7).value()); + EXPECT_EQ(3, vector_under_test.find_last_index(5).value()); } TEST(VectorTest, FindAllIndicesEmptyVector) { - const vector vector_under_test; - EXPECT_EQ(0, vector_under_test.find_all_indices(-3).size()); + const vector vector_under_test; + EXPECT_EQ(0, vector_under_test.find_all_indices(-3).size()); } TEST(VectorTest, FindAllIndicesFilledVectorWithoutMatch) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_EQ(0, vector_under_test.find_all_indices(9).size()); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_EQ(0, vector_under_test.find_all_indices(9).size()); } TEST(VectorTest, FindAllIndicesFilledVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 9, 1}); - const auto one_indices = vector_under_test.find_all_indices(1); - EXPECT_EQ(std::vector({ 0, 6, 8 }), one_indices); - const auto seven_indices = vector_under_test.find_all_indices(9); - EXPECT_EQ(std::vector({ 7 }), seven_indices); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 9, 1}); + const auto one_indices = vector_under_test.find_all_indices(1); + EXPECT_EQ(std::vector({ 0, 6, 8 }), one_indices); + const auto seven_indices = vector_under_test.find_all_indices(9); + EXPECT_EQ(std::vector({ 7 }), seven_indices); } TEST(VectorTest, RemoveAtEmptyVector) { - vector vector_under_test; - EXPECT_DEATH(vector_under_test.remove_at(-1), ""); - EXPECT_DEATH(vector_under_test.remove_at(0), ""); - EXPECT_DEATH(vector_under_test.remove_at(1), ""); + vector vector_under_test; + EXPECT_DEATH(vector_under_test.remove_at(-1), ""); + EXPECT_DEATH(vector_under_test.remove_at(0), ""); + EXPECT_DEATH(vector_under_test.remove_at(1), ""); } TEST(VectorTest, RemoveAtFilledVectorAboveSize) { - auto vector_under_test = vector({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_DEATH(vector_under_test.remove_at(15), ""); + auto vector_under_test = vector({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_DEATH(vector_under_test.remove_at(15), ""); } TEST(VectorTest, RemoveAtFilledVector) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.remove_at(1); - EXPECT_EQ(vector({ 1, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); - vector_under_test.remove_at(1); - EXPECT_EQ(vector({ 1, 5, 8, 3, 1, 7, 1 }), vector_under_test); - vector_under_test.remove_at(4); - EXPECT_EQ(vector({ 1, 5, 8, 3, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.remove_at(1); + EXPECT_EQ(vector({ 1, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector_under_test.remove_at(1); + EXPECT_EQ(vector({ 1, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector_under_test.remove_at(4); + EXPECT_EQ(vector({ 1, 5, 8, 3, 7, 1 }), vector_under_test); } TEST(VectorTest, RemovingAtEmptyVector) { - const vector vector_under_test; - EXPECT_DEATH(vector_under_test.removing_at(-1), ""); - EXPECT_DEATH(vector_under_test.removing_at(0), ""); - EXPECT_DEATH(vector_under_test.removing_at(1), ""); + const vector vector_under_test; + EXPECT_DEATH(vector_under_test.removing_at(-1), ""); + EXPECT_DEATH(vector_under_test.removing_at(0), ""); + EXPECT_DEATH(vector_under_test.removing_at(1), ""); } TEST(VectorTest, RemovingAtFilledVectorAboveSize) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_DEATH(vector_under_test.removing_at(15), ""); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_DEATH(vector_under_test.removing_at(15), ""); } TEST(VectorTest, RemovingAtFilledVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto shorter_vector = vector_under_test.removing_at(1); - EXPECT_EQ(vector({ 1, 2, 5, 8, 3, 1, 7, 1 }), shorter_vector); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto shorter_vector = vector_under_test.removing_at(1); + EXPECT_EQ(vector({ 1, 2, 5, 8, 3, 1, 7, 1 }), shorter_vector); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, RemoveBack) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.remove_back(); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7 }), vector_under_test); - vector_under_test.remove_back(); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1 }), vector_under_test); - vector_under_test.remove_back(); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.remove_back(); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7 }), vector_under_test); + vector_under_test.remove_back(); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1 }), vector_under_test); + vector_under_test.remove_back(); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3 }), vector_under_test); } TEST(VectorTest, RemovingBack) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto vector_without_last_element = vector_under_test.removing_back(); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7 }), vector_without_last_element); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto vector_without_last_element = vector_under_test.removing_back(); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7 }), vector_without_last_element); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, RemoveFront) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.remove_front(); - EXPECT_EQ(vector({ 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); - vector_under_test.remove_front(); - EXPECT_EQ(vector({ 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); - vector_under_test.remove_front(); - EXPECT_EQ(vector({ 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.remove_front(); + EXPECT_EQ(vector({ 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector_under_test.remove_front(); + EXPECT_EQ(vector({ 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector_under_test.remove_front(); + EXPECT_EQ(vector({ 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, RemovingFront) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto vector_without_first_element = vector_under_test.removing_front(); - EXPECT_EQ(vector({ 4, 2, 5, 8, 3, 1, 7, 1 }), vector_without_first_element); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto vector_without_first_element = vector_under_test.removing_front(); + EXPECT_EQ(vector({ 4, 2, 5, 8, 3, 1, 7, 1 }), vector_without_first_element); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); } + TEST(VectorTest, InsertAtEmptyVector) { - vector vector_under_test; - EXPECT_DEATH(vector_under_test.insert_at(15, -1), ""); - vector_under_test.insert_at(0, -1); - EXPECT_EQ(1, vector_under_test.size()); - EXPECT_EQ(-1, vector_under_test[0]); + vector vector_under_test; + EXPECT_DEATH(vector_under_test.insert_at(15, -1), ""); + vector_under_test.insert_at(0, -1); + EXPECT_EQ(1, vector_under_test.size()); + EXPECT_EQ(-1, vector_under_test[0]); } TEST(VectorTest, InsertAtFilledVector) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_DEATH(vector_under_test.insert_at(15, -1), ""); - vector_under_test.insert_at(3, 18); - EXPECT_EQ(vector({ 1, 4, 2, 18, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_DEATH(vector_under_test.insert_at(15, -1), ""); + vector_under_test.insert_at(3, 18); + EXPECT_EQ(vector({ 1, 4, 2, 18, 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, InsertingAtEmptyVector) { - const vector vector_under_test; - EXPECT_DEATH(vector_under_test.inserting_at(15, -1), ""); - const auto augmented_vector = vector_under_test.inserting_at(0, -1); - EXPECT_EQ(1, augmented_vector.size()); - EXPECT_EQ(-1, augmented_vector[0]); - EXPECT_EQ(0, vector_under_test.size()); + const vector vector_under_test; + EXPECT_DEATH(vector_under_test.inserting_at(15, -1), ""); + const auto augmented_vector = vector_under_test.inserting_at(0, -1); + EXPECT_EQ(1, augmented_vector.size()); + EXPECT_EQ(-1, augmented_vector[0]); + EXPECT_EQ(0, vector_under_test.size()); } TEST(VectorTest, InsertingAtFilledVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_DEATH(vector_under_test.inserting_at(15, -1), ""); - const auto augmented_vector = vector_under_test.inserting_at(3, 18); - EXPECT_EQ(vector({ 1, 4, 2, 18, 5, 8, 3, 1, 7, 1 }), augmented_vector); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_DEATH(vector_under_test.inserting_at(15, -1), ""); + const auto augmented_vector = vector_under_test.inserting_at(3, 18); + EXPECT_EQ(vector({ 1, 4, 2, 18, 5, 8, 3, 1, 7, 1 }), augmented_vector); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, InsertRangeEmptyFunctionalVector) { - vector vector_under_test; - const vector vector_to_insert({4, 7, 3, -5}); - vector_under_test.insert_at(0, vector_to_insert); - EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); + vector vector_under_test; + const vector vector_to_insert({4, 7, 3, -5}); + vector_under_test.insert_at(0, vector_to_insert); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); } TEST(VectorTest, InsertRangeExistingWrongInsertionIndexFunctionalVector) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const vector vector_to_insert({9, -5, 6}); - EXPECT_DEATH(vector_under_test.insert_at(-1, vector_to_insert), ""); - EXPECT_DEATH(vector_under_test.insert_at(10, vector_to_insert), ""); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const vector vector_to_insert({9, -5, 6}); + EXPECT_DEATH(vector_under_test.insert_at(-1, vector_to_insert), ""); + EXPECT_DEATH(vector_under_test.insert_at(10, vector_to_insert), ""); } TEST(VectorTest, InsertRangeExistingFunctionalVector) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const vector vector_to_insert({9, -5, 6}); - vector_under_test.insert_at(3, vector_to_insert); - EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const vector vector_to_insert({9, -5, 6}); + vector_under_test.insert_at(3, vector_to_insert); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, InsertRangeEmptyStdVector) { - vector vector_under_test; - const std::vector vector_to_insert{4, 7, 3, -5}; - vector_under_test.insert_at(0, vector_to_insert); - EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); + vector vector_under_test; + const std::vector vector_to_insert{4, 7, 3, -5}; + vector_under_test.insert_at(0, vector_to_insert); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); } TEST(VectorTest, InsertRangeExistingWrongInsertionIndexStdVector) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const std::vector vector_to_insert({9, -5, 6}); - EXPECT_DEATH(vector_under_test.insert_at(-1, vector_to_insert), ""); - EXPECT_DEATH(vector_under_test.insert_at(10, vector_to_insert), ""); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const std::vector vector_to_insert({9, -5, 6}); + EXPECT_DEATH(vector_under_test.insert_at(-1, vector_to_insert), ""); + EXPECT_DEATH(vector_under_test.insert_at(10, vector_to_insert), ""); } TEST(VectorTest, InsertRangeExistingStdVector) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const std::vector vector_to_insert({9, -5, 6}); - vector_under_test.insert_at(3, vector_to_insert); - EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const std::vector vector_to_insert({9, -5, 6}); + vector_under_test.insert_at(3, vector_to_insert); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, InsertRangeEmptyInitializerList) { - vector vector_under_test; - vector_under_test.insert_at(0, {4, 7, 3, -5}); - EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); + vector vector_under_test; + vector_under_test.insert_at(0, {4, 7, 3, -5}); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); } TEST(VectorTest, InsertRangeExistingWrongInsertionIndexInitializerList) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_DEATH(vector_under_test.insert_at(-1, { 9, -5, 6 }), ""); - EXPECT_DEATH(vector_under_test.insert_at(10, { 9, -5, 6 }), ""); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_DEATH(vector_under_test.insert_at(-1, { 9, -5, 6 }), ""); + EXPECT_DEATH(vector_under_test.insert_at(10, { 9, -5, 6 }), ""); } TEST(VectorTest, InsertRangeExistingInitializerList) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.insert_at(3, {9, -5, 6}); - EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.insert_at(3, {9, -5, 6}); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, InsertingRangeEmptyFunctionalVector) { - const vector vector_under_test; - const vector vector_to_insert({4, 7, 3, -5}); - const auto result_vector = vector_under_test.inserting_at(0, vector_to_insert); - EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); + const vector vector_under_test; + const vector vector_to_insert({4, 7, 3, -5}); + const auto result_vector = vector_under_test.inserting_at(0, vector_to_insert); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); } TEST(VectorTest, InsertingRangeExistingWrongInsertionIndexFunctionalVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const vector vector_to_insert({9, -5, 6}); - EXPECT_DEATH(vector_under_test.inserting_at(-1, vector_to_insert), ""); - EXPECT_DEATH(vector_under_test.inserting_at(10, vector_to_insert), ""); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const vector vector_to_insert({9, -5, 6}); + EXPECT_DEATH(vector_under_test.inserting_at(-1, vector_to_insert), ""); + EXPECT_DEATH(vector_under_test.inserting_at(10, vector_to_insert), ""); } TEST(VectorTest, InsertingRangeExistingFunctionalVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const vector vector_to_insert({9, -5, 6}); - const auto result_vector = vector_under_test.inserting_at(3, vector_to_insert); - EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const vector vector_to_insert({9, -5, 6}); + const auto result_vector = vector_under_test.inserting_at(3, vector_to_insert); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); } TEST(VectorTest, InsertingRangeEmptyStdVector) { - const vector vector_under_test; - const std::vector vector_to_insert({4, 7, 3, -5}); - const auto result_vector = vector_under_test.inserting_at(0, vector_to_insert); - EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); + const vector vector_under_test; + const std::vector vector_to_insert({4, 7, 3, -5}); + const auto result_vector = vector_under_test.inserting_at(0, vector_to_insert); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); } TEST(VectorTest, InsertingRangeExistingWrongInsertionIndexStdVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const std::vector vector_to_insert({9, -5, 6}); - EXPECT_DEATH(vector_under_test.inserting_at(-1, vector_to_insert), ""); - EXPECT_DEATH(vector_under_test.inserting_at(10, vector_to_insert), ""); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const std::vector vector_to_insert({9, -5, 6}); + EXPECT_DEATH(vector_under_test.inserting_at(-1, vector_to_insert), ""); + EXPECT_DEATH(vector_under_test.inserting_at(10, vector_to_insert), ""); } TEST(VectorTest, InsertingRangeExistingStdVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const std::vector vector_to_insert({9, -5, 6}); - const auto result_vector = vector_under_test.inserting_at(3, vector_to_insert); - EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const std::vector vector_to_insert({9, -5, 6}); + const auto result_vector = vector_under_test.inserting_at(3, vector_to_insert); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); } TEST(VectorTest, InsertingRangeEmptyInitializerList) { - const vector vector_under_test; - const auto result_vector = vector_under_test.inserting_at(0, {4, 7, 3, -5}); - EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); + const vector vector_under_test; + const auto result_vector = vector_under_test.inserting_at(0, {4, 7, 3, -5}); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); } TEST(VectorTest, InsertingRangeExistingWrongInsertionIndexInitializerList) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_DEATH(vector_under_test.inserting_at(-1, { 9, -5, 6 }), ""); - EXPECT_DEATH(vector_under_test.inserting_at(10, { 9, -5, 6 }), ""); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_DEATH(vector_under_test.inserting_at(-1, { 9, -5, 6 }), ""); + EXPECT_DEATH(vector_under_test.inserting_at(10, { 9, -5, 6 }), ""); } TEST(VectorTest, InsertingRangeExistingInitializerList) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto result_vector = vector_under_test.inserting_at(3, {9, -5, 6}); - EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto result_vector = vector_under_test.inserting_at(3, {9, -5, 6}); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); } TEST(VectorTest, RemoveIndexRangeWithInvalidRange) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.remove_range(index_range::invalid); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.remove_range(index_range::invalid); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, RemoveIndexRangeEmptyVector) { - vector vector_under_test; - vector_under_test.remove_range(index_range::start_count(1, 12)); - EXPECT_EQ(vector(), vector_under_test); + vector vector_under_test; + vector_under_test.remove_range(index_range::start_count(1, 12)); + EXPECT_EQ(vector(), vector_under_test); } TEST(VectorTest, RemoveIndexRangeStartCountSuccess) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.remove_range(index_range::start_count(2, 3)); - EXPECT_EQ(vector({ 1, 4, 3, 1, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.remove_range(index_range::start_count(2, 3)); + EXPECT_EQ(vector({ 1, 4, 3, 1, 7, 1 }), vector_under_test); } TEST(VectorTest, RemoveRangeStartEndSuccess) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.remove_range(index_range::start_end(3, 6)); - EXPECT_EQ(vector({ 1, 4, 2, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.remove_range(index_range::start_end(3, 6)); + EXPECT_EQ(vector({ 1, 4, 2, 7, 1 }), vector_under_test); } TEST(VectorTest, RemovingIndexRangeWithInvalidRange) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto shorter_vector = vector_under_test.removing_range(index_range::invalid); - EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), shorter_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto shorter_vector = vector_under_test.removing_range(index_range::invalid); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), shorter_vector); } TEST(VectorTest, RemovingRangeEmptyVector) { - const vector vector_under_test; - const auto shorter_vector = vector_under_test.removing_range(index_range::start_count(1, 12)); - EXPECT_EQ(vector(), shorter_vector); + const vector vector_under_test; + const auto shorter_vector = vector_under_test.removing_range(index_range::start_count(1, 12)); + EXPECT_EQ(vector(), shorter_vector); } TEST(VectorTest, RemovingIndexRangeStartCountSuccess) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto shorter_vector = vector_under_test.removing_range(index_range::start_count(2, 3)); - EXPECT_EQ(vector({ 1, 4, 3, 1, 7, 1 }), shorter_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto shorter_vector = vector_under_test.removing_range(index_range::start_count(2, 3)); + EXPECT_EQ(vector({ 1, 4, 3, 1, 7, 1 }), shorter_vector); } TEST(VectorTest, RemovingIndexRangeStartEndSuccess) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto shorter_vector = vector_under_test.removing_range(index_range::start_end(3, 6)); - EXPECT_EQ(vector({ 1, 4, 2, 7, 1 }), shorter_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto shorter_vector = vector_under_test.removing_range(index_range::start_end(3, 6)); + EXPECT_EQ(vector({ 1, 4, 2, 7, 1 }), shorter_vector); } TEST(VectorTest, ReplaceRangeAtWithEmptySource) { - vector vector_under_test({5, -3, 4, -9}); - vector_under_test.replace_range_at(3, std::vector()); - EXPECT_EQ(vector({ 5, -3 , 4, -9 }), vector_under_test); + vector vector_under_test({5, -3, 4, -9}); + vector_under_test.replace_range_at(3, std::vector()); + EXPECT_EQ(vector({ 5, -3 , 4, -9 }), vector_under_test); } TEST(VectorTest, ReplaceRangeAtWrongIndex) { - vector vector_under_test({5, -3, 4, -9}); - EXPECT_DEATH(vector_under_test.replace_range_at(-1, { 1, 2, 6, 4 }), ""); - EXPECT_DEATH(vector_under_test.replace_range_at(4, { 1, 2, 6, 4 }), ""); - EXPECT_DEATH(vector_under_test.replace_range_at(5, { 1, 2, 6, 4 }), ""); + vector vector_under_test({5, -3, 4, -9}); + EXPECT_DEATH(vector_under_test.replace_range_at(-1, { 1, 2, 6, 4 }), ""); + EXPECT_DEATH(vector_under_test.replace_range_at(4, { 1, 2, 6, 4 }), ""); + EXPECT_DEATH(vector_under_test.replace_range_at(5, { 1, 2, 6, 4 }), ""); } TEST(VectorTest, ReplaceRangeAtMoreElementsInSourceThanCapacity) { - vector vector_under_test({5, -3, 4, -9}); - EXPECT_DEATH(vector_under_test.replace_range_at(2, { 1, 2, 6, 4, 8, 9, -10 }), ""); + vector vector_under_test({5, -3, 4, -9}); + EXPECT_DEATH(vector_under_test.replace_range_at(2, { 1, 2, 6, 4, 8, 9, -10 }), ""); } TEST(VectorTest, ReplaceRangeAtWithFunctionalVector) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.replace_range_at(4, vector({9, -10, 8})); - EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.replace_range_at(4, vector({9, -10, 8})); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); } TEST(VectorTest, ReplaceRangeAtWithStdVector) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.replace_range_at(4, std::vector({9, -10, 8})); - EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.replace_range_at(4, std::vector({9, -10, 8})); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); } TEST(VectorTest, ReplaceRangeAtWithInitializerList) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.replace_range_at(4, std::initializer_list({9, -10, 8})); - EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.replace_range_at(4, std::initializer_list({9, -10, 8})); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); } TEST(VectorTest, ReplacingRangeAtWithEmptySource) { - const vector vector_under_test({5, -3, 4, -9}); - const auto replaced_vector = vector_under_test.replacing_range_at(3, std::vector()); - EXPECT_EQ(vector({ 5, -3 , 4, -9 }), replaced_vector); + const vector vector_under_test({5, -3, 4, -9}); + const auto replaced_vector = vector_under_test.replacing_range_at(3, std::vector()); + EXPECT_EQ(vector({ 5, -3 , 4, -9 }), replaced_vector); } TEST(VectorTest, ReplacingRangeAtWrongIndex) { - const vector vector_under_test({5, -3, 4, -9}); - EXPECT_DEATH(vector_under_test.replacing_range_at(-1, { 1, 2, 6, 4 }), ""); - EXPECT_DEATH(vector_under_test.replacing_range_at(4, { 1, 2, 6, 4 }), ""); - EXPECT_DEATH(vector_under_test.replacing_range_at(5, { 1, 2, 6, 4 }), ""); + const vector vector_under_test({5, -3, 4, -9}); + EXPECT_DEATH(vector_under_test.replacing_range_at(-1, { 1, 2, 6, 4 }), ""); + EXPECT_DEATH(vector_under_test.replacing_range_at(4, { 1, 2, 6, 4 }), ""); + EXPECT_DEATH(vector_under_test.replacing_range_at(5, { 1, 2, 6, 4 }), ""); } TEST(VectorTest, ReplacingRangeAtMoreElementsInSourceThanCapacity) { - const vector vector_under_test({5, -3, 4, -9}); - EXPECT_DEATH(vector_under_test.replacing_range_at(2, { 1, 2, 6, 4, 8, 9, -10 }), ""); + const vector vector_under_test({5, -3, 4, -9}); + EXPECT_DEATH(vector_under_test.replacing_range_at(2, { 1, 2, 6, 4, 8, 9, -10 }), ""); } TEST(VectorTest, ReplacingRangeAtWithFunctionalVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto replaced_vector = vector_under_test.replacing_range_at(4, vector({9, -10, 8})); - EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto replaced_vector = vector_under_test.replacing_range_at(4, vector({9, -10, 8})); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); } TEST(VectorTest, ReplacingRangeAtWithStdVector) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto replaced_vector = vector_under_test.replacing_range_at(4, std::vector({9, -10, 8})); - EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto replaced_vector = vector_under_test.replacing_range_at(4, std::vector({9, -10, 8})); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); } TEST(VectorTest, ReplacingRangeAtWithInitializerList) { - const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto replaced_vector = vector_under_test.replacing_range_at(4, std::initializer_list({9, -10, 8})); - EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto replaced_vector = vector_under_test.replacing_range_at(4, std::initializer_list({9, -10, 8})); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); } TEST(VectorTest, Fill) { - vector vector_under_test({1, 3, -6, 4, -9}); - vector_under_test.fill(7); - EXPECT_EQ(vector({ 7, 7, 7, 7, 7 }), vector_under_test); + vector vector_under_test({1, 3, -6, 4, -9}); + vector_under_test.fill(7); + EXPECT_EQ(vector({ 7, 7, 7, 7, 7 }), vector_under_test); } TEST(VectorTest, RepeatingConstructor) { - const vector vector_under_test(3, "John"); - EXPECT_EQ(vector({ "John", "John", "John" }), vector_under_test); + const vector vector_under_test(3, "John"); + EXPECT_EQ(vector({ "John", "John", "John" }), vector_under_test); } TEST(VectorTest, EqualityOperatorEmptyVectors) { - const vector vec1; - const vector vec2; - EXPECT_TRUE(vec1 == vec2); - EXPECT_FALSE(vec1 != vec2); + const vector vec1; + const vector vec2; + EXPECT_TRUE(vec1 == vec2); + EXPECT_FALSE(vec1 != vec2); } TEST(VectorTest, EqualityOperatorUnequalSizes) { - const vector vec1({1, 2, 3}); - const vector vec2({1, 2, 3, 4}); - EXPECT_TRUE(vec1 != vec2); - EXPECT_FALSE(vec1 == vec2); + const vector vec1({1, 2, 3}); + const vector vec2({1, 2, 3, 4}); + EXPECT_TRUE(vec1 != vec2); + EXPECT_FALSE(vec1 == vec2); } TEST(VectorTest, EqualityOperatorEqualSizesDifferentElements) { - const vector vec1({1, 2, 3}); - const vector vec2({1, 2, 4}); - EXPECT_TRUE(vec1 != vec2); - EXPECT_FALSE(vec1 == vec2); + const vector vec1({1, 2, 3}); + const vector vec2({1, 2, 4}); + EXPECT_TRUE(vec1 != vec2); + EXPECT_FALSE(vec1 == vec2); } TEST(VectorTest, EqualityOperatorEqualVectors) { - const vector vec1({1, 2, 3}); - const vector vec2({1, 2, 3}); - EXPECT_TRUE(vec1 == vec2); - EXPECT_FALSE(vec1 != vec2); + const vector vec1({1, 2, 3}); + const vector vec2({1, 2, 3}); + EXPECT_TRUE(vec1 == vec2); + EXPECT_FALSE(vec1 != vec2); } TEST(VectorTest, EqualityOperatorCustomTypeEqualVectors) { - const vector vec1({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); + const vector vec1({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + const vector vec2({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); - const vector vec2({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); - - EXPECT_TRUE(vec1 == vec2); - EXPECT_FALSE(vec1 != vec2); + EXPECT_TRUE(vec1 == vec2); + EXPECT_FALSE(vec1 != vec2); } TEST(VectorTest, EqualityOperatorCustomTypeUnequalSizes) { - const vector vec1({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); - - const vector vec2({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate"), - person(50, "Barbara") - }); + const vector vec1({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + const vector vec2({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate"), + person(50, "Barbara") + }); - EXPECT_FALSE(vec1 == vec2); - EXPECT_TRUE(vec1 != vec2); + EXPECT_FALSE(vec1 == vec2); + EXPECT_TRUE(vec1 != vec2); } TEST(VectorTest, EqualityOperatorCustomTypeUnequalVectors) { - const vector vec1({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate") - }); + const vector vec1({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + const vector vec2({ + person(15, "Jake"), + person(53, "Bob"), + person(35, "Suzan") + }); - const vector vec2({ - person(15, "Jake"), - person(53, "Bob"), - person(35, "Suzan") - }); - - EXPECT_FALSE(vec1 == vec2); - EXPECT_TRUE(vec1 != vec2); + EXPECT_FALSE(vec1 == vec2); + EXPECT_TRUE(vec1 != vec2); } TEST(VectorTest, ClearEmptyVector) { - vector vector_under_test; - EXPECT_TRUE(vector_under_test.is_empty()); - vector_under_test.clear(); - EXPECT_EQ(0, vector_under_test.size()); - EXPECT_TRUE(vector_under_test.is_empty()); + vector vector_under_test; + EXPECT_TRUE(vector_under_test.is_empty()); + vector_under_test.clear(); + EXPECT_EQ(0, vector_under_test.size()); + EXPECT_TRUE(vector_under_test.is_empty()); } TEST(VectorTest, ClearFilledVector) { - vector vector_under_test({5, -3, 4, -9}); - EXPECT_FALSE(vector_under_test.is_empty()); - vector_under_test.clear(); - EXPECT_EQ(0, vector_under_test.size()); - EXPECT_TRUE(vector_under_test.is_empty()); + vector vector_under_test({5, -3, 4, -9}); + EXPECT_FALSE(vector_under_test.is_empty()); + vector_under_test.clear(); + EXPECT_EQ(0, vector_under_test.size()); + EXPECT_TRUE(vector_under_test.is_empty()); } TEST(VectorTest, CapacityReserveClear) { - vector vector_under_test; - EXPECT_EQ(0, vector_under_test.capacity()); - EXPECT_EQ(0, vector_under_test.size()); - - vector_under_test.reserve(5); - EXPECT_EQ(5, vector_under_test.capacity()); - EXPECT_EQ(0, vector_under_test.size()); - - vector_under_test.insert_back({1, 4, -5, 2}); - EXPECT_EQ(5, vector_under_test.capacity()); - EXPECT_EQ(4, vector_under_test.size()); - - vector_under_test.clear(); - EXPECT_EQ(5, vector_under_test.capacity()); - EXPECT_EQ(0, vector_under_test.size()); + vector vector_under_test; + EXPECT_EQ(0, vector_under_test.capacity()); + EXPECT_EQ(0, vector_under_test.size()); + + vector_under_test.reserve(5); + EXPECT_EQ(5, vector_under_test.capacity()); + EXPECT_EQ(0, vector_under_test.size()); + + vector_under_test.insert_back({1, 4, -5, 2}); + EXPECT_EQ(5, vector_under_test.capacity()); + EXPECT_EQ(4, vector_under_test.size()); + + vector_under_test.clear(); + EXPECT_EQ(5, vector_under_test.capacity()); + EXPECT_EQ(0, vector_under_test.size()); } TEST(VectorTest, ResizeEmptyVector) { - vector vector_under_test; - vector_under_test.resize(5); - EXPECT_EQ(vector({ 0, 0, 0, 0, 0 }), vector_under_test); - EXPECT_EQ(5, vector_under_test.capacity()); - EXPECT_EQ(5, vector_under_test.size()); + vector vector_under_test; + vector_under_test.resize(5); + EXPECT_EQ(vector({ 0, 0, 0, 0, 0 }), vector_under_test); + EXPECT_EQ(5, vector_under_test.capacity()); + EXPECT_EQ(5, vector_under_test.size()); } TEST(VectorTest, ResizeSmallerThanCurrentSize) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_EQ(9, vector_under_test.capacity()); - EXPECT_EQ(9, vector_under_test.size()); - - vector_under_test.resize(5); - EXPECT_EQ(vector({1, 4, 2, 5, 8}), vector_under_test); - EXPECT_EQ(9, vector_under_test.capacity()); - EXPECT_EQ(5, vector_under_test.size()); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_EQ(9, vector_under_test.capacity()); + EXPECT_EQ(9, vector_under_test.size()); + + vector_under_test.resize(5); + EXPECT_EQ(vector({1, 4, 2, 5, 8}), vector_under_test); + EXPECT_EQ(9, vector_under_test.capacity()); + EXPECT_EQ(5, vector_under_test.size()); } TEST(VectorTest, AllOfFalse) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_FALSE(vector_under_test.all_of([](const int& number) { return number > 5; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_FALSE(vector_under_test.all_of([](const int& number) { return number > 5; })); } TEST(VectorTest, AllOfTrue) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.all_of([](const int& number){ - return number < 10; - }); - EXPECT_TRUE(vector_under_test.all_of([](const int& number) { return number < 10; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.all_of([](const int& number) { + return number < 10; + }); + EXPECT_TRUE(vector_under_test.all_of([](const int& number) { return number < 10; })); } #ifdef PARALLEL_ALGORITHM_AVAILABLE TEST(VectorTest, AllOfParallelFalse) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_FALSE(vector_under_test.all_of_parallel([](const int& number) { return number > 5; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_FALSE(vector_under_test.all_of_parallel([](const int& number) { return number > 5; })); } TEST(VectorTest, AllOfParallelTrue) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.all_of([](const int& number){ - return number < 10; - }); - EXPECT_TRUE(vector_under_test.all_of_parallel([](const int& number) { return number < 10; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector_under_test.all_of([](const int& number) { + return number < 10; + }); + EXPECT_TRUE(vector_under_test.all_of_parallel([](const int& number) { return number < 10; })); } #endif TEST(VectorTest, AnyOfFalse) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_FALSE(vector_under_test.any_of([](const int& number) { return number > 20; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_FALSE(vector_under_test.any_of([](const int& number) { return number > 20; })); } TEST(VectorTest, AnyOfTrue) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_TRUE(vector_under_test.any_of([](const int& number) { return number >= 7; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_TRUE(vector_under_test.any_of([](const int& number) { return number >= 7; })); } #ifdef PARALLEL_ALGORITHM_AVAILABLE TEST(VectorTest, AnyOfParallelFalse) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_FALSE(vector_under_test.any_of_parallel([](const int& number) { return number > 20; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_FALSE(vector_under_test.any_of_parallel([](const int& number) { return number > 20; })); } TEST(VectorTest, AnyOfParallelTrue) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_TRUE(vector_under_test.any_of_parallel([](const int& number) { return number >= 7; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_TRUE(vector_under_test.any_of_parallel([](const int& number) { return number >= 7; })); } #endif TEST(VectorTest, NoneOfFalse) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_FALSE(vector_under_test.none_of([](const int& number) { return number > 7; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_FALSE(vector_under_test.none_of([](const int& number) { return number > 7; })); } TEST(VectorTest, NoneOfTrue) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_TRUE(vector_under_test.none_of([](const int& number) { return number < -2; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_TRUE(vector_under_test.none_of([](const int& number) { return number < -2; })); } #ifdef PARALLEL_ALGORITHM_AVAILABLE TEST(VectorTest, NoneOfParallelFalse) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_FALSE(vector_under_test.none_of_parallel([](const int& number) { return number > 7; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_FALSE(vector_under_test.none_of_parallel([](const int& number) { return number > 7; })); } TEST(VectorTest, NoneOfParallelTrue) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_TRUE(vector_under_test.none_of_parallel([](const int& number) { return number < -2; })); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_TRUE(vector_under_test.none_of_parallel([](const int& number) { return number < -2; })); } TEST(VectorTest, ForEachParallel) { - vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - EXPECT_EQ(9, vector_under_test.size()); - std::atomic counter(0); - vector_under_test.for_each_parallel([&](const int& element){ ++counter; }); - EXPECT_EQ(9, counter); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + EXPECT_EQ(9, vector_under_test.size()); + std::atomic counter(0); + vector_under_test.for_each_parallel([&](const int& element) { ++counter; }); + EXPECT_EQ(9, counter); } #endif TEST(VectorTest, Distinct) { - const vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto& unique_numbers = numbers.distinct(); - EXPECT_EQ(set({1, 2, 3, 4, 5, 7, 8}), unique_numbers); + const vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const auto& unique_numbers = numbers.distinct(); + EXPECT_EQ(set({1, 2, 3, 4, 5, 7, 8}), unique_numbers); } TEST(VectorTest, DistinctCustomType) { - const vector persons({ - person(15, "Jake"), - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate"), - person(25, "Kate"), - person(62, "Bob") - }); - - const auto& unique_persons = persons.distinct(); - - const set expected({ - person(15, "Jake"), - person(18, "Jannet"), - person(25, "Kate"), - person(62, "Bob") - }); - - EXPECT_EQ(expected, unique_persons); + const vector persons({ + person(15, "Jake"), + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate"), + person(25, "Kate"), + person(62, "Bob") + }); + + const auto& unique_persons = persons.distinct(); + + const set expected({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate"), + person(62, "Bob") + }); + + EXPECT_EQ(expected, unique_persons); } - -#pragma warning( pop )