diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 35786ad..3f4d35c 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -27,7 +27,7 @@ jobs: cc: "cl", cxx: "cl", environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat", - generators: "Visual Studio 16 2019" + generators: "Visual Studio 17 2022" } - { name: "Windows Latest MSVC (C++17)", @@ -36,7 +36,7 @@ jobs: cc: "cl", cxx: "cl", environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat", - generators: "Visual Studio 16 2019" + generators: "Visual Studio 17 2022" } - { name: "Ubuntu Latest GCC (C++11)", diff --git a/CMakeLists.txt b/CMakeLists.txt index d0c189a..980f4e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.14) -project(functional_vector VERSION 0.9) +project(functional_cpp VERSION 1.0) # GoogleTest requires at least C++11 if(NOT "${CMAKE_CXX_STANDARD}") diff --git a/LICENSE b/LICENSE index 4064ca5..0720e25 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Ioannis Kaliakatsos +Copyright (c) 2022 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 58a7386..1e4aa24 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,14 @@ -[![CMake Build Matrix](https://github.com/jkalias/functional_vector/actions/workflows/cmake.yml/badge.svg)](https://github.com/jkalias/functional_vector/actions/workflows/cmake.yml) -[![GitHub license](https://img.shields.io/github/license/jkalias/functional_vector)](https://github.com/jkalias/functional_vector/blob/main/LICENSE) -# Say hello to functional C++ vectors -A wrapper for C++ std::vector geared towards functional programming and fluent APIs. -The primary focus is readability at the call site (not performance) and eliminating manual management of vector indices. -This is heavily influenced and inspired by C# and Swift. +[![CMake Build Matrix](https://github.com/jkalias/functional_cpp/actions/workflows/cmake.yml/badge.svg)](https://github.com/jkalias/functional_cpp/actions/workflows/cmake.yml) +[![GitHub license](https://img.shields.io/github/license/jkalias/functional_cpp)](https://github.com/jkalias/functional_cpp/blob/main/LICENSE) +# Say hello to functional C++ +A wrapper for C++ std::vector and std::set geared towards functional programming and fluent APIs. This project is heavily influenced and inspired by C# and Swift. + +The primary focus of this library is +* readability at the call site ("make it work, make it right, make it fast") +* surfacing existing algorithms from the standard library, and lowering the barrier for their extended usage +* elimination of vector index operations +* encapsulation of the iterator madness +* removal of manual for-loops ## Compilation (Cmake) ### Dependencies @@ -15,23 +20,23 @@ This is heavily influenced and inspired by C# and Swift. An out-of-source build strategy is used. All following examples assume an output build folder named ```build```. If no additional argument is passed to CMake, C++11 is used. Otherwise, you can pass ```-DCMAKE_CXX_STANDARD=17``` and it will use C++17 for example. ### macOS (Xcode) ```console -cd functional_vector +cd functional_cpp cmake -S . -B build -G Xcode ``` -Then open the generated ```functional_vector.xcodeproj``` in the ```build``` folder. +Then open the generated ```functional_cpp.xcodeproj``` in the ```build``` folder. ### macOS (Makefiles/clang) ```console -cd functional_vector +cd functional_cpp cmake -S . -B build cmake --build build build/tests/unit_tests ``` ### macOS (Makefiles/g++) -Assuming you have installed Homebrew, then you can use the gcc and g++ compilers by doing the following (this example uses version gcc 11) +Assuming you have installed Homebrew, you can then use the gcc and g++ compilers by doing the following (this example uses version gcc 11) ```console -cd functional_vector +cd functional_cpp cmake \ -S . \ -B build \ @@ -43,7 +48,7 @@ build/tests/unit_tests ### Linux (Makefiles) ```console -cd functional_vector +cd functional_cpp cmake -S . -B build cmake --build build build/tests/unit_tests @@ -51,15 +56,25 @@ build/tests/unit_tests ### Windows (Visual Studio) ```console -cd functional_vector +cd functional_cpp cmake -S . -B build ``` -Then open the generated ```functional_vector.sln``` in the ```build``` folder. +Then open the generated ```functional_cpp.sln``` in the ```build``` folder. + +## Functional vector usage (fcpp::vector) +### extract unique (distinct) elements +```c++ +#include "vector.h" // instead of + +const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + +// contains only 1, 2, 3, 4, 5, 7, 8 +const auto& unique_numbers = numbers.distinct(); +``` -## Usage ### zip, map, filter, sort ```c++ -#include "functional_vector.h" // instead of +#include "vector.h" // instead of struct person { person(int age, std::string name) @@ -67,32 +82,41 @@ struct person { {} int age; std::string name; + + std::size_t hash() const { + // a clever implementation of hash + // ... + } + + bool operator< (const person& other) const { + return hash() < other.hash(); + } }; // ... // the employees' ages -const functional_vector ages({32, 45, 37, 23}); +const fcpp::vector ages({32, 45, 37, 23}); // the employees' names -const functional_vector names({"Jake", "Anna", "Kate", "Bob"}); +const fcpp::vector names({"Jake", "Anna", "Kate", "Bob"}); const auto employees_below_40 = ages // zip two vectors for simultaneous processing .zip(names) // apply the functional map algorithm (transform from one type to another) - .map([](const auto& pair) { + .map([](const std::pair& pair) { return person(pair.first, pair.second); }) // filter the elements using a local function (lambda) - .filter([](const auto& person) { - return person.age < 40; + .filter([](const person& p) { + return p.age < 40; }) // sort according to custom predicate - .sort([](const auto& person1, const auto& person2) { + .sort([](const person& person1, const person& person2) { return person1.age < person2.age; }); @@ -102,15 +126,15 @@ const auto employees_below_40 = ages Jake is 32 years old. Kate is 37 years old. */ -employees_below_40.for_each([](const auto& person) { - std::cout << person.name << " is " << person.age << " years old." << std::endl; +employees_below_40.for_each([](const person& p) { + std::cout << p.name << " is " << p.age << " years old." << std::endl; }); ``` ### index search ```c++ -#include "functional_vector.h" // instead of +#include "vector.h" // instead of -const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); +const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); const auto first_index_of_one = numbers.find_first_index(1); // returns 0 @@ -130,63 +154,63 @@ index_of_nine.has_value(); ### remove, insert ```c++ -#include "functional_vector.h" // instead of +#include "vector.h" // instead of #include "index_range.h" -functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); +fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); -// numbers -> functional_vector({1, 4, 2, 5, 3, 1, 7, 1}); +// numbers -> fcpp::vector({1, 4, 2, 5, 3, 1, 7, 1}); numbers.remove_at(4); -// numbers -> functional_vector({4, 2, 5, 3, 1, 7, 1}); +// numbers -> fcpp::vector({4, 2, 5, 3, 1, 7, 1}); numbers.remove_front(); -// numbers -> functional_vector({4, 2, 5, 3, 1, 7}); +// numbers -> fcpp::vector({4, 2, 5, 3, 1, 7}); numbers.remove_back(); -// numbers -> functional_vector({4, 2, 7}); +// numbers -> fcpp::vector({4, 2, 7}); numbers.remove_range(index_range::start_count(2, 3)); -// numbers -> functional_vector({4, 8, 2, 7}); +// numbers -> fcpp::vector({4, 8, 2, 7}); numbers.insert_at(1, 8); -// numbers -> functional_vector({-10, 4, 8, 2, 7}); +// numbers -> fcpp::vector({-10, 4, 8, 2, 7}); numbers.insert_front(-10); -// numbers -> functional_vector({-10, 4, 8, 2, 7, 9}); +// numbers -> fcpp::vector({-10, 4, 8, 2, 7, 9}); numbers.insert_back(9); -// numbers -> functional_vector({-10, 4, 8, 3, -2, 5, 2, 7, 9}); +// numbers -> fcpp::vector({-10, 4, 8, 3, -2, 5, 2, 7, 9}); numbers.insert_at(3, std::vector({3, -2, 5})); -// numbers -> functional_vector({4, -6, 7, -10, 4, 8, 3, -2, 5, 2, 7, 9}); -numbers.insert_front(functional_vector({4, -6, 7})); +// numbers -> fcpp::vector({4, -6, 7, -10, 4, 8, 3, -2, 5, 2, 7, 9}); +numbers.insert_front(fcpp::vector({4, -6, 7})); -// numbers -> functional_vector({4, -6, 7, -10, 4, 8, 3, -2, 5, 2, 7, 9, 7, 3}); +// numbers -> fcpp::vector({4, -6, 7, -10, 4, 8, 3, -2, 5, 2, 7, 9, 7, 3}); numbers.insert_back(std::initializer_list({7, 3})); ``` -### size/capacity, reserve/resize +### size, capacity, reserve, resize ```c++ -#include "functional_vector.h" // instead of +#include "vector.h" // instead of // numbers.capacity() = 9 // numbers.size() = 9 -functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); +fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); -// numbers -> functional_vector({1, 4, 2, 5, 8}); +// numbers -> fcpp::vector({1, 4, 2, 5, 8}); // numbers.capacity() = 9 // numbers.size() = 5 numbers.resize(5); -// numbers -> functional_vector({1, 4, 2, 5, 8, 0, 0}); +// numbers -> fcpp::vector({1, 4, 2, 5, 8, 0, 0}); // numbers.capacity() = 9 // numbers.size() = 7 numbers.resize(7); // empty_numbers.capacity() = 0 // empty_numbers.size() = 0 -functional_vector empty_numbers; +fcpp::vector empty_numbers; // empty_numbers.capacity() = 5 // empty_numbers.size() = 0 @@ -195,37 +219,37 @@ empty_numbers.reserve(5); ### all_of, any_of, none_of ```c++ -#include "functional_vector.h" // instead of +#include "vector.h" // instead of -functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); +fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // returns true -numbers.all_of([](const auto &number) { +numbers.all_of([](const int& number) { return number < 10; }); // returns false -numbers.all_of([](const auto &number) { +numbers.all_of([](const int& number) { return number > 2; }); // returns true -numbers.any_of([](const auto &number) { +numbers.any_of([](const int& number) { return number < 5; }); // returns false -numbers.any_of([](const auto &number) { +numbers.any_of([](const int& number) { return number > 9; }); // returns true -numbers.none_of([](const auto &number) { +numbers.none_of([](const int& number) { return number < -2; }); // returns false -numbers.none_of([](const auto &number) { +numbers.none_of([](const int& number) { return number > 7; }); ``` @@ -233,7 +257,7 @@ numbers.none_of([](const auto &number) { ### Parallel algorithms Since C++17 several STL algorithms can be executed in parallel. -clang on macOS does not yet fully support the parallel execution model, however on Windows and Linux, a `functional_vector` supports the following parallel algorithms +clang on macOS does not yet fully support the parallel execution model, however on Windows and Linux, an `fcpp::vector` supports the following parallel algorithms ```c++ for_each_parallel map_parallel @@ -243,3 +267,149 @@ all_of_parallel any_of_parallel none_of_parallel ``` + +## Functional set usage (fcpp::set) +### difference, union, intersection (works with fcpp::set and std::set) +```c++ +#include "set.h" // instead of + +// struct person as defined previously +struct person_comparator { + bool operator() (const person& a, const person& b) const { + return a < b; + } +}; + +// ... + +// a set containing all colleagues +const fcpp::set colleagues({ + person(51, "George"), + person(15, "Jake"), + person(18, "Jannet"), + person(41, "Jackie"), + person(25, "Kate") +}); + +// a set containing all friends +const fcpp::set friends({ + person(51, "George"), + person(41, "Jackie"), + person(42, "Crystal"), +}); + +// find which colleagues are not friends +// contains person(15, "Jake"), person(18, "Jannet") and person(25, "Kate") +const auto colleagues_but_not_friends = colleagues.difference_with(friends); + +// find which friends are colleagues +// same as colleagues.intersect_with(friends) +// contains person(51, "George"), person(41, "Jackie") +const auto good_colleagues = friends.intersection_with(colleagues); + +// a set of close family members +const fcpp::set family({ + person(51, "Paul"), + person(81, "Barbara"), +}); + +// all of our friends and family for the next party invitation +// contains person(51, "George"), person(41, "Jackie"), person(42, "Crystal"), person(51, "Paul"), person(81, "Barbara") +const auto friends_and_family = friends.union_with(family); +``` + +### zip, map, filter +```c++ +#include "set.h" // instead of + +// the employees' ages +const fcpp::set ages({ 25, 45, 30, 63 }); + +// the employees' names +const fcpp::set names({ "Jake", "Bob", "Michael", "Philipp" }); + +const auto employees_below_40 = ages + // zip two sets for simultaneous processing + .zip(names) + + // apply the functional map algorithm (transform from one type to another) + .map([](const std::pair& pair) { + return person(pair.first, pair.second); + }) + + // filter the elements using a local function (lambda) + .filter([](const person& p) { + return p.age < 40; + }); + +/* + prints the following: + Jake is 30 years old. + Bob is 25 years old. + */ +employees_below_40.for_each([](const person& p) { + std::cout << p.name << " is " << p.age << " years old." << std::endl; +}); +``` + +### all_of, any_of, none_of +```c++ +#include "set.h" // instead of + +fcpp::set numbers({1, 4, 2, 5, 8, 3, 7}); + +// returns true +numbers.all_of([](const int& number) { + return number < 10; +}); + +// returns false +numbers.all_of([](const int& number) { + return number > 2; +}); + +// returns true +numbers.any_of([](const int& number) { + return number < 5; +}); + +// returns false +numbers.any_of([](const int& number) { + return number > 9; +}); + +// returns true +numbers.none_of([](const int& number) { + return number < -2; +}); + +// returns false +numbers.none_of([](const int& number) { + return number > 7; +}); +``` + +### remove, insert, contains, size, clear +```c++ +#include "set.h" // instead of + +fcpp::set numbers({1, 2, 3, 4, 5, 7, 8}); + +// numbers -> fcpp::set numbers({1, 2, 3, 5, 7, 8}); +numbers.remove(4); + +// numbers -> fcpp::set numbers({1, 2, 3, 5, 7, 8, 10}); +numbers.insert(10); + +// returns true +numbers.contains(10); + +// returns false +numbers.contains(25); + +// returns 7 +numbers.size(); + +// removes all keys +numbers.clear(); +``` diff --git a/include/export_def.h b/include/export_def.h index 1959f51..f8b9b0c 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_VECTOR_EXPORTS - #define FunctionalVectorExport __declspec( dllexport ) + #ifdef FUNCTIONAL_CPP_EXPORTS + #define FunctionalCppExport __declspec( dllexport ) #else - #define FunctionalVectorExport __declspec( dllimport ) + #define FunctionalCppExport __declspec( dllimport ) #endif #else - #define FunctionalVectorExport __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 7c82a4e..b1cbf3f 100644 --- a/include/index_range.h +++ b/include/index_range.h @@ -24,7 +24,7 @@ #include "export_def.h" // A struct used for container safe access based on index -struct FunctionalVectorExport index_range +struct FunctionalCppExport index_range { // Used for returning values of invalid operations static index_range invalid; diff --git a/include/optional.h b/include/optional.h index 59a803d..cea05b7 100644 --- a/include/optional.h +++ b/include/optional.h @@ -24,6 +24,8 @@ #pragma once #include "compatibility.h" +namespace fcpp { + #ifdef CPP17_AVAILABLE #include template @@ -98,3 +100,5 @@ template using optional_t = optional; #endif + +} diff --git a/include/set.h b/include/set.h new file mode 100644 index 0000000..ed7a054 --- /dev/null +++ b/include/set.h @@ -0,0 +1,676 @@ +// MIT License +// +// Copyright (c) 2022 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::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() + : backing_set_() + { + } + + explicit set(std::set set) + : backing_set_(std::move(set)) + { + } + + explicit set(const std::vector& vector) + : backing_set_(vector.begin(), vector.end()) + { + } + + explicit set(const vector& vector) + : backing_set_(vector.begin(), vector.end()) + { + } + + explicit set(const std::initializer_list& list) + : backing_set_(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: backing_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 >> +#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 `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); + } + } + backing_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 >> +#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; + } + + // 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) + { + backing_set_.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(backing_set_); + 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) + { + backing_set_.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(backing_set_); + 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() + { + backing_set_.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 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 backing_set_.count(key) != 0; + } + + // Returns the size of the vector (how many elements it contains, it may be different from its capacity) + [[nodiscard]] size_t size() const + { + return backing_set_.size(); + } + + // clear + // is_empty + + // Returns the begin iterator, useful for other standard library algorithms + [[nodiscard]] typename std::set::iterator begin() + { + return backing_set_.begin(); + } + + // Returns the const begin iterator, useful for other standard library algorithms + [[nodiscard]] typename std::set::const_iterator begin() const + { + return backing_set_.begin(); + } + + // Returns the end iterator, useful for other standard library algorithms + [[nodiscard]] typename std::set::iterator end() + { + return backing_set_.end(); + } + + // Returns the const end iterator, useful for other standard library algorithms + [[nodiscard]] typename std::set::const_iterator end() const + { + return backing_set_.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::set backing_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; +#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/functional_vector.h b/include/vector.h similarity index 69% rename from include/functional_vector.h rename to include/vector.h index c65b098..7f39572 100644 --- a/include/functional_vector.h +++ b/include/vector.h @@ -21,15 +21,20 @@ // SOFTWARE. #pragma once -#include #include #include +#include #include "index_range.h" #include "optional.h" #ifdef PARALLEL_ALGORITHM_AVAILABLE #include #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. @@ -37,24 +42,25 @@ // Member functions can be mutating (eg. my_vector.reverse()) or // non-mutating (eg. my_vector.reversed()) enforcing thread safety if needed template -class functional_vector +class vector { public: - functional_vector() + vector() : backing_vector_() { } - explicit functional_vector(const std::vector& vector) + explicit vector(const std::vector& vector) : backing_vector_(vector) { } - explicit functional_vector(std::vector&& vector) + explicit vector(std::vector&& vector) : backing_vector_(std::move(vector)) { } - explicit functional_vector(std::initializer_list list) + + explicit vector(std::initializer_list list) : backing_vector_(std::move(list)) { } @@ -62,11 +68,11 @@ class functional_vector // Creates a new vector by repeating a given element. // // example: - // const functional_vector filled_vector(3, "John"); + // const fcpp::vector filled_vector(3, "John"); // // outcome: - // filled_vector -> functional_vector({ "John", "John", "John" }) - explicit functional_vector(size_t count, const T& element) + // filled_vector -> fcpp::vector({ "John", "John", "John" }) + explicit vector(size_t count, const T& element) : backing_vector_(count, element) { } @@ -75,17 +81,17 @@ class functional_vector // output of applying the transform function on every element of this instance. // // example: - // const functional_vector input_vector({ 1, 3, -5 }); + // 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 -> functional_vector({ "1", "3", "-5" }) + // output_vector -> fcpp::vector({ "1", "3", "-5" }) // // is equivalent to: - // const functional_vector input_vector({ 1, 3, -5 }); - // functional_vector output_vector; + // 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])); // } @@ -94,7 +100,7 @@ class functional_vector #else template #endif - functional_vector map(Transform && transform) const + vector map(Transform && transform) const { std::vector transformed_vector; transformed_vector.reserve(backing_vector_.size()); @@ -102,14 +108,14 @@ class functional_vector backing_vector_.end(), std::back_inserter(transformed_vector), std::forward(transform)); - return functional_vector(transformed_vector); + return vector(transformed_vector); } #ifdef PARALLEL_ALGORITHM_AVAILABLE // Performs the functional `map` algorithm in parallel. // See also the sequential version for more documentation. template >> - functional_vector map_parallel(Transform && transform) const + vector map_parallel(Transform && transform) const { std::vector transformed_vector; transformed_vector.resize(backing_vector_.size()); @@ -118,14 +124,14 @@ class functional_vector backing_vector_.cend(), transformed_vector.begin(), std::forward(transform)); - return functional_vector(transformed_vector); + return vector(transformed_vector); } #endif // Returns true if all elements match the predicate (return true) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // // // returns true // numbers.all_of([](const auto &number) { @@ -143,8 +149,8 @@ class functional_vector #endif bool all_of(Callable && unary_predicate) const { - return std::all_of(cbegin(), - cend(), + return std::all_of(begin(), + end(), std::forward(unary_predicate)); } @@ -155,8 +161,8 @@ class functional_vector bool all_of_parallel(Callable && unary_predicate) const { return std::all_of(std::execution::par, - cbegin(), - cend(), + begin(), + end(), std::forward(unary_predicate)); } #endif @@ -164,7 +170,7 @@ class functional_vector // Returns true if at least one of the elements matches the predicate (returns true) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // // // returns true // numbers.any_of([](const auto &number) { @@ -182,8 +188,8 @@ class functional_vector #endif bool any_of(Callable && unary_predicate) const { - return std::any_of(cbegin(), - cend(), + return std::any_of(begin(), + end(), std::forward(unary_predicate)); } @@ -194,8 +200,8 @@ class functional_vector bool any_of_parallel(Callable && unary_predicate) const { return std::any_of(std::execution::par, - cbegin(), - cend(), + begin(), + end(), std::forward(unary_predicate)); } #endif @@ -203,7 +209,7 @@ class functional_vector // Returns true if no element matches the predicate (all return false) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // // // returns true // numbers.none_of([](const auto &number) { @@ -221,8 +227,8 @@ class functional_vector #endif bool none_of(Callable && unary_predicate) const { - return std::none_of(cbegin(), - cend(), + return std::none_of(begin(), + end(), std::forward(unary_predicate)); } @@ -233,8 +239,8 @@ class functional_vector bool none_of_parallel(Callable && unary_predicate) const { return std::none_of(std::execution::par, - cbegin(), - cend(), + begin(), + end(), std::forward(unary_predicate)); } #endif @@ -243,16 +249,16 @@ class functional_vector // which match the given predicate are kept (mutating) // // example: - // functional_vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); // numbers.filter([](const auto& element) { // return element >= 1.5; // }); // // outcome: - // numbers -> functional_vector({ 3, 2, 9 }); + // numbers -> fcpp::vector({ 3, 2, 9 }); // // is equivalent to: - // functional_vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // fcpp::vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); // for (auto i = 0; i < numbers.size(); ++i) { // if (numbers[i] >= 1.5) { // continue; @@ -265,7 +271,7 @@ class functional_vector #else template #endif - functional_vector& filter(Filter && predicate_to_keep) + vector& filter(Filter && predicate_to_keep) { backing_vector_.erase(std::remove_if(backing_vector_.begin(), backing_vector_.end(), @@ -279,7 +285,7 @@ class functional_vector // Performs the functional `filter` algorithm in parallel. // See also the sequential version for more documentation. template >> - functional_vector& filter_parallel(Filter && predicate_to_keep) + vector& filter_parallel(Filter && predicate_to_keep) { backing_vector_.erase(std::remove_if(std::execution::par, backing_vector_.begin(), @@ -292,21 +298,21 @@ class functional_vector #endif // Performs the functional `filter` algorithm in a copy of this instance, in which all elements of - // the copy which match the given predicate (non-mutating) + // the copy which match the given predicate are kept (non-mutating) // // example: - // const functional_vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); + // 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 -> functional_vector({ 1, 3, -5, 2, -1, 9, -4 }) - // filtered_numbers -> functional_vector({ 3, 2, 9 }) + // numbers -> fcpp::vector({ 1, 3, -5, 2, -1, 9, -4 }) + // filtered_numbers -> fcpp::vector({ 3, 2, 9 }) // // is equivalent to: - // const functional_vector numbers({ 1, 3, -5, 2, -1, 9, -4 }); - // functional_vector filtered_numbers; + // 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]); @@ -317,7 +323,7 @@ class functional_vector #else template #endif - functional_vector filtered(Callable && predicate_to_keep) const + vector filtered(Callable && predicate_to_keep) const { std::vector filtered_vector; filtered_vector.reserve(backing_vector_.size()); @@ -325,14 +331,14 @@ class functional_vector backing_vector_.end(), std::back_inserter(filtered_vector), std::forward(predicate_to_keep)); - return functional_vector(filtered_vector); + return vector(filtered_vector); } #ifdef PARALLEL_ALGORITHM_AVAILABLE // Performs the `filtered` algorithm in parallel. // See also the sequential version for more documentation. template >> - functional_vector filtered_parallel(Callable && predicate_to_keep) const + 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 @@ -347,7 +353,7 @@ class functional_vector backing_vector_.end(), std::back_inserter(filtered_vector), std::forward(predicate_to_keep)); - return functional_vector(filtered_vector); + return vector(filtered_vector); #endif } #endif @@ -355,12 +361,12 @@ class functional_vector // Reverses the order of the elements in place (mutating) // // example: - // functional_vector numbers_vector({ 1, 3, -5, 2, -1, 9, -4 }); + // fcpp::vector numbers_vector({ 1, 3, -5, 2, -1, 9, -4 }); // numbers_vector.reverse(); // // outcome: - // numbers_vector -> functional_vector({ -4, 9, -1, 2, -5, 3, 1 }) - functional_vector& reverse() + // numbers_vector -> fcpp::vector({ -4, 9, -1, 2, -5, 3, 1 }) + vector& reverse() { std::reverse(backing_vector_.begin(), backing_vector_.end()); return *this; @@ -369,25 +375,18 @@ class functional_vector // Returns a copy of this instance, whose elements are in reverse order (non-mutating) // // example: - // const functional_vector input_vector({ 1, 3, -5, 2, -1, 9, -4 }); + // const fcpp::vector input_vector({ 1, 3, -5, 2, -1, 9, -4 }); // const auto reversed_vector = input_vector.reversed(); // // outcome: - // input_vector -> functional_vector({ 1, 3, -5, 2, -1, 9, -4 }); - // reversed_vector -> functional_vector({ -4, 9, -1, 2, -5, 3, 1 }) - [[nodiscard]] functional_vector reversed() const + // 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(backing_vector_.crbegin(), backing_vector_.crend()); - return functional_vector(std::move(reversed_vector)); + return vector(std::move(reversed_vector)); } - template - struct pair - { - T first; - U second; - }; - #ifdef CPP17_AVAILABLE template using deref_type = typename std::iterator_traits::value_type; @@ -403,34 +402,34 @@ class functional_vector // index. The sizes of the two vectors must be equal. // // example: - // const functional_vector ages_vector({32, 25, 53}); - // const functional_vector names_vector({"Jake", "Mary", "John"}); + // 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 -> functional_vector::pair>({ + // zipped_vector -> fcpp::vector>({ // (32, "Jake"), // (25, "Mary"), // (53, "John"), // }) // // is equivalent to: - // const functional_vector ages_vector({32, 25, 53}); - // const functional_vector names_vector({"Jake", "Mary", "John"}); - // functional_vector::pair> zipped_vector; + // 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) { - // functional_vector::pair tuple; + // fcpp::vector::pair tuple; // tuple.first = ages_vector[i]; // tuple.second = names_vector[i]; // zipped_vector.insert_back(tuple); // } template - [[nodiscard]] functional_vector> zip(const functional_vector& vector) const + [[nodiscard]] vector> zip(const vector& vector) const { #ifdef CPP17_AVAILABLE - return zip_impl(vector.cbegin(), vector.cend()); + return zip_impl(vector.begin(), vector.end()); #else - return zip_impl(vector.cbegin(), vector.cend()); + return zip_impl(vector.begin(), vector.end()); #endif } @@ -439,29 +438,29 @@ class functional_vector // index. The sizes of the two vectors must be equal. // // example: - // const functional_vector ages_vector({32, 25, 53}); + // 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 -> functional_vector::pair>({ + // zipped_vector -> fcpp::vector>({ // (32, "Jake"), // (25, "Mary"), // (53, "John"), // }) // // is equivalent to: - // const functional_vector ages_vector({32, 25, 53}); + // const fcpp::vector ages_vector({32, 25, 53}); // const std::vector names_vector({"Jake", "Mary", "John"}); - // functional_vector::pair> zipped_vector; + // fcpp::vector> zipped_vector; // for (auto i = 0; i < ages_vector.size(); ++i) { - // functional_vector::pair tuple; + // fcpp::vector::pair tuple; // tuple.first = ages_vector[i]; // tuple.second = names_vector[i]; // zipped_vector.insert_back(tuple); // } template - [[nodiscard]] functional_vector> zip(const std::vector& vector) const + [[nodiscard]] vector> zip(const std::vector& vector) const { #ifdef CPP17_AVAILABLE return zip_impl(vector.cbegin(), vector.cend()); @@ -471,29 +470,29 @@ class functional_vector } // example: - // const functional_vector ages_vector({32, 25, 53}); + // 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 -> functional_vector::pair>({ + // zipped_vector -> fcpp::vector>({ // (32, "Jake"), // (25, "Mary"), // (53, "John"), // }) // // is equivalent to: - // const functional_vector ages_vector({32, 25, 53}); + // const fcpp::vector ages_vector({32, 25, 53}); // const std::initializer_list names_vector({"Jake", "Mary", "John"}); - // functional_vector::pair> zipped_vector; + // fcpp::vector> zipped_vector; // for (auto i = 0; i < ages_vector.size(); ++i) { - // functional_vector::pair tuple; + // fcpp::vector::pair tuple; // tuple.first = ages_vector[i]; // tuple.second = names_vector[i]; // zipped_vector.insert_back(tuple); // } template - [[nodiscard]] functional_vector> zip(const std::initializer_list& list) const + [[nodiscard]] vector> zip(const std::initializer_list& list) const { #ifdef CPP17_AVAILABLE return zip_impl(list.begin(), list.end()); @@ -512,7 +511,7 @@ class functional_vector // std::string name; // }; // ... - // functional_vector persons_vector({ + // 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) { @@ -520,7 +519,7 @@ class functional_vector // }); // // outcome: - // person_vector -> functional_vector({ + // person_vector -> fcpp::vector({ // person(8, "Alice"), person(34, "Bob"), person(45, "Jake"), person(52, "Manfred") // }); #ifdef CPP17_AVAILABLE @@ -528,7 +527,7 @@ class functional_vector #else template #endif - functional_vector& sort(Sortable && comparison_predicate) + vector& sort(Sortable && comparison_predicate) { std::sort(backing_vector_.begin(), backing_vector_.end(), @@ -540,7 +539,7 @@ class functional_vector // Performs the `sort` algorithm in parallel. // See also the sequential version for more documentation. template >> - functional_vector& sort_parallel(Sortable && comparison_predicate) + vector& sort_parallel(Sortable && comparison_predicate) { std::sort(std::execution::par, backing_vector_.begin(), @@ -553,12 +552,12 @@ class functional_vector // Sorts the vector in place in ascending order, when its elements support comparison by std::less_equal [<=] (mutating). // // example: - // functional_vector numbers({3, 1, 9, -4}); + // fcpp::vector numbers({3, 1, 9, -4}); // numbers.sort_ascending(); // // outcome: - // numbers -> functional_vector({-4, 1, 3, 9}); - functional_vector& sort_ascending() + // numbers -> fcpp::vector({-4, 1, 3, 9}); + vector& sort_ascending() { return sort(std::less_equal()); } @@ -566,7 +565,7 @@ class functional_vector #ifdef PARALLEL_ALGORITHM_AVAILABLE // Performs the `sort_ascending` algorithm in parallel. // See also the sequential version for more documentation. - functional_vector& sort_ascending_parallel() + vector& sort_ascending_parallel() { return sort_parallel(std::less_equal()); } @@ -575,12 +574,12 @@ class functional_vector // Sorts the vector in place in descending order, when its elements support comparison by std::greater_equal [>=] (mutating). // // example: - // functional_vector numbers({3, 1, 9, -4}); + // fcpp::vector numbers({3, 1, 9, -4}); // numbers.sort_ascending(); // // outcome: - // numbers -> functional_vector({9, 3, 1, -4}); - functional_vector& sort_descending() + // numbers -> fcpp::vector({9, 3, 1, -4}); + vector& sort_descending() { return sort(std::greater_equal()); } @@ -588,7 +587,7 @@ class functional_vector #ifdef PARALLEL_ALGORITHM_AVAILABLE // Performs the `sort_ascending` algorithm in parallel. // See also the sequential version for more documentation. - functional_vector& sort_descending_parallel() + vector& sort_descending_parallel() { return sort_parallel(std::greater_equal()); } @@ -604,7 +603,7 @@ class functional_vector // std::string name; // }; // ... - // const functional_vector persons_vector({ + // 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) { @@ -612,7 +611,7 @@ class functional_vector // }); // // outcome: - // sorted_persons_vector -> functional_vector({ + // sorted_persons_vector -> fcpp::vector({ // person(8, "Alice"), person(34, "Bob"), person(45, "Jake"), person(52, "Manfred") // }); #ifdef CPP17_AVAILABLE @@ -620,39 +619,39 @@ class functional_vector #else template #endif - functional_vector sorted(Sortable && comparison_predicate) const + vector sorted(Sortable && comparison_predicate) const { auto sorted_vector(backing_vector_); std::sort(sorted_vector.begin(), sorted_vector.end(), std::forward(comparison_predicate)); - return functional_vector(sorted_vector); + return vector(sorted_vector); } #ifdef PARALLEL_ALGORITHM_AVAILABLE // Performs the `sorted` algorithm in parallel. // See also the sequential version for more documentation. template >> - functional_vector sorted_parallel(Sortable && comparison_predicate) const + vector sorted_parallel(Sortable && comparison_predicate) const { auto sorted_vector(backing_vector_); std::sort(std::execution::par, sorted_vector.begin(), sorted_vector.end(), std::forward(comparison_predicate)); - return functional_vector(sorted_vector); + return fcpp::vector(sorted_vector); } #endif // Sorts its elements copied and sorted in ascending order, when its elements support comparison by std::less_equal [<=] (non-mutating). // // example: - // const functional_vector numbers({3, 1, 9, -4}); + // const fcpp::vector numbers({3, 1, 9, -4}); // auto sorted_numbers = numbers.sorted_ascending(); // // outcome: - // sorted_numbers -> functional_vector({-4, 1, 3, 9}); - [[nodiscard]] functional_vector sorted_ascending() const + // sorted_numbers -> fcpp::vector({-4, 1, 3, 9}); + [[nodiscard]] vector sorted_ascending() const { return sorted(std::less_equal()); } @@ -660,7 +659,7 @@ class functional_vector #ifdef PARALLEL_ALGORITHM_AVAILABLE // Performs the `sorted_ascending` algorithm in parallel. // See also the sequential version for more documentation. - [[nodiscard]] functional_vector sorted_ascending_parallel() const + [[nodiscard]] vector sorted_ascending_parallel() const { return sorted_parallel(std::less_equal()); } @@ -669,12 +668,12 @@ class functional_vector // Sorts its elements copied and sorted in descending order, when its elements support comparison by std::greater_equal [>=] (non-mutating). // // example: - // const functional_vector numbers({3, 1, 9, -4}); + // const fcpp::vector numbers({3, 1, 9, -4}); // auto sorted_numbers = numbers.sorted_descending(); // // outcome: - // sorted_numbers -> functional_vector({9, 3, 1, -4}); - [[nodiscard]] functional_vector sorted_descending() const + // sorted_numbers -> fcpp::vector({9, 3, 1, -4}); + [[nodiscard]] vector sorted_descending() const { return sorted(std::greater_equal()); } @@ -682,7 +681,7 @@ class functional_vector #ifdef PARALLEL_ALGORITHM_AVAILABLE // Performs the `sorted_descending` algorithm in parallel. // See also the sequential version for more documentation. - [[nodiscard]] functional_vector sorted_descending_parallel() const + [[nodiscard]] vector sorted_descending_parallel() const { return sorted_parallel(std::greater_equal()); } @@ -695,7 +694,7 @@ class functional_vector #else template #endif - const functional_vector& for_each(Callable && operation) const + const vector& for_each(Callable && operation) const { std::for_each(backing_vector_.cbegin(), backing_vector_.cend(), @@ -707,7 +706,7 @@ class functional_vector // 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 functional_vector& for_each_parallel(Callable && operation) const + const vector& for_each_parallel(Callable && operation) const { std::for_each(std::execution::par, backing_vector_.cbegin(), @@ -719,10 +718,10 @@ class functional_vector // 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 occurences). + // (see find_all_indices for multiple occurrences). // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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); // @@ -730,7 +729,7 @@ class functional_vector // index_of_one.value() -> 0 // index_of_one.has_value() -> true // index_of_nine.has_value() -> false - [[nodiscard]] optional_t find_first_index(const T& element) const + [[nodiscard]] fcpp::optional_t find_first_index(const T& element) const { auto const it = std::find(backing_vector_.cbegin(), backing_vector_.cend(), @@ -739,7 +738,7 @@ class functional_vector auto index = std::distance(backing_vector_.cbegin(), it); return index; } - return optional_t(); + return fcpp::optional_t(); } // Returns the last index in which the given element is found in the vector. @@ -747,7 +746,7 @@ class functional_vector // (see find_all_indices for multiple occurrences). // // example: - // const functional_vector numbers({1, 4, 2, 5, -6, 3, 1, 7, 1}); + // 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); // @@ -755,7 +754,7 @@ class functional_vector // index_of_one.value() -> 8 // index_of_one.has_value() -> true // index_of_nine.has_value() -> false - [[nodiscard]] optional_t find_last_index(const T& element) const + [[nodiscard]] fcpp::optional_t find_last_index(const T& element) const { auto const it = std::find(backing_vector_.crbegin(), backing_vector_.crend(), @@ -764,13 +763,13 @@ class functional_vector auto index = std::distance(it, backing_vector_.crend()) - 1; return index; } - return optional_t(); + return fcpp::optional_t(); } // Returns all indices in which the given element is found in the vector. // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 9, 1}); + // 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); // @@ -795,12 +794,12 @@ class functional_vector // Removes the element at `index` (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // numbers.remove_at(4); // // outcome: - // numbers -> functional_vector({1, 4, 2, 5, 3, 1, 7, 1}); - functional_vector& remove_at(int index) + // numbers -> fcpp::vector({1, 4, 2, 5, 3, 1, 7, 1}); + vector& remove_at(int index) { assert_smaller_size(index); backing_vector_.erase(begin() + index); @@ -810,28 +809,28 @@ class functional_vector // Returns a copy of itself in which the element at `index` is removed (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // auto shorter_vector = numbers.removing_at(4); // // outcome: - // shorter_vector -> functional_vector({1, 4, 2, 5, 3, 1, 7, 1}); - [[nodiscard]] functional_vector removing_at(int index) const + // 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(backing_vector_); copy.erase(copy.begin() + index); - return functional_vector(copy); + return vector(copy); } // Removes the last element, if present (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // numbers.remove_back(); // // outcome: - // numbers -> functional_vector({1, 4, 2, 5, 8, 3, 1, 7}); - functional_vector& remove_back() + // numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7}); + vector& remove_back() { backing_vector_.pop_back(); return *this; @@ -840,27 +839,27 @@ class functional_vector // Returns a copy of itself in which the last element is removed (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // auto shorter_vector = numbers.removing_back(); // // outcome: - // shorter_vector -> functional_vector({1, 4, 2, 5, 8, 3, 1, 7}); - [[nodiscard]] functional_vector removing_back() const + // shorter_vector -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7}); + [[nodiscard]] vector removing_back() const { auto copy(backing_vector_); copy.pop_back(); - return functional_vector(copy); + return vector(copy); } // Removes the first element, if present (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // numbers.remove_front(); // // outcome: - // numbers -> functional_vector({4, 2, 5, 8, 3, 1, 7, 1}); - functional_vector& remove_front() + // numbers -> fcpp::vector({4, 2, 5, 8, 3, 1, 7, 1}); + vector& remove_front() { if (size() == 0) { @@ -872,12 +871,12 @@ class functional_vector // Returns a copy of itself in which the first element is removed (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // auto shorter_numbers = numbers.removing_front(); // // outcome: - // shorter_numbers -> functional_vector({4, 2, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] functional_vector removing_front() const + // shorter_numbers -> fcpp::vector({4, 2, 5, 8, 3, 1, 7, 1}); + [[nodiscard]] vector removing_front() const { if (size() == 0) { @@ -889,12 +888,12 @@ class functional_vector // Removes the elements whose index is contained in the given index range (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // numbers.remove_range(index_range::start_count(2, 3)); // // outcome: - // numbers -> functional_vector({ 1, 4, 2, 7, 1 }) - functional_vector& remove_range(index_range range) + // numbers -> fcpp::vector({ 1, 4, 2, 7, 1 }) + vector& remove_range(index_range range) { if (!range.is_valid || size() < range.end + 1) { @@ -908,12 +907,12 @@ class functional_vector // Returns a copy by removing the elements whose index is contained in the given index range (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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 -> functional_vector({ 1, 4, 3, 1, 7, 1 }) - [[nodiscard]] functional_vector removing_range(index_range range) const + // 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) { @@ -922,18 +921,18 @@ class functional_vector auto shorter_vector(backing_vector_); shorter_vector.erase(shorter_vector.begin() + range.start, shorter_vector.begin() + range.start + range.count); - return functional_vector(shorter_vector); + return vector(shorter_vector); } // Inserts an element at the given index, therefore changing the vector's contents (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // numbers.insert_at(3, 18); // // outcome: - // numbers -> functional_vector({1, 4, 2, 18, 5, 8, 3, 1, 7, 1}); - functional_vector& insert_at(int index, const T& element) + // 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); backing_vector_.insert(begin() + index, element); @@ -943,57 +942,57 @@ class functional_vector // Returns a copy by inserting an element at the given index (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // auto augmented_numbers = numbers.inserting_at(3, 18); // // outcome: - // augmented_numbers -> functional_vector({1, 4, 2, 18, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] functional_vector inserting_at(int index, const T& element) const + // 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(backing_vector_); copy.insert(copy.begin() + index, element); - return functional_vector(copy); + return vector(copy); } // Inserts a range of elements starting at the given index, therefore changing the vector's contents (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const functional_vector vector_to_insert({9, -5, 6}); + // 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 -> functional_vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - functional_vector& insert_at(int index, const functional_vector& vector) + // 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.cbegin(), vector.cend()); + 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 functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // const functional_vector vector_to_insert({9, -5, 6}); + // 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 -> functional_vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] functional_vector inserting_at(int index, const functional_vector& vector) const + // 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.cbegin(), vector.cend()); + 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: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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 -> functional_vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - functional_vector& insert_at(int index, const std::vector& vector) + // 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()); } @@ -1001,13 +1000,13 @@ class functional_vector // Returns a copy by inserting a range of elements starting at the given index (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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 -> functional_vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] functional_vector inserting_at(int index, const std::vector& vector) const + // 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()); } @@ -1015,13 +1014,13 @@ class functional_vector // Inserts a range of elements starting at the given index, therefore changing the vector's contents (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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 -> functional_vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - functional_vector& insert_at(int index, std::initializer_list list) + // 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))); } @@ -1029,13 +1028,13 @@ class functional_vector // Returns a copy by inserting a range of elements starting at the given index (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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 -> functional_vector({1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] functional_vector inserting_at(int index, std::initializer_list list) const + // 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))); } @@ -1043,12 +1042,12 @@ class functional_vector // Inserts a value at the end of the vector in place (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // numbers.insert_back(18); // // outcome: - // numbers -> functional_vector({1, 4, 2, 5, 8, 3, 1, 7, 1, 18}); - functional_vector& insert_back(T value) + // numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7, 1, 18}); + vector& insert_back(T value) { backing_vector_.push_back(value); return *this; @@ -1057,12 +1056,12 @@ class functional_vector // Inserts a value at the beginning of the vector in place (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // numbers.insert_front(18); // // outcome: - // numbers -> functional_vector({18, 1, 4, 2, 5, 8, 3, 1, 7, 1}); - functional_vector& insert_front(T value) + // numbers -> fcpp::vector({18, 1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector& insert_front(T value) { return insert_at(0, value); } @@ -1070,27 +1069,27 @@ class functional_vector // Makes a copy of the vector, inserts value at the end of the copy and returns the copy (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // auto augmented_numbers = numbers.inserting_back(18); // // outcome: - // augmented_numbers -> functional_vector({1, 4, 2, 5, 8, 3, 1, 7, 1, 18}); - [[nodiscard]] functional_vector inserting_back(T value) const + // augmented_numbers -> fcpp::vector({1, 4, 2, 5, 8, 3, 1, 7, 1, 18}); + [[nodiscard]] vector inserting_back(T value) const { auto augmented_vector(backing_vector_); augmented_vector.push_back(value); - return functional_vector(augmented_vector); + 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 functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // const fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // auto augmented_numbers = numbers.inserting_front(18); // // outcome: - // augmented_numbers -> functional_vector({18, 1, 4, 2, 5, 8, 3, 1, 7, 1}); - [[nodiscard]] functional_vector inserting_front(T value) const + // 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); } @@ -1098,64 +1097,64 @@ class functional_vector // Inserts a range of values at the end of the vector in place (mutating) // // example: - // functional_vector numbers({ 4, 5, 6 }); - // numbers.insert_back(functional_vector({1, 2, 3})); + // fcpp::vector numbers({ 4, 5, 6 }); + // numbers.insert_back(fcpp::vector({1, 2, 3})); // // outcome: - // numbers -> functional_vector numbers({ 4, 5, 6, 1, 2, 3 }); - functional_vector& insert_back(const functional_vector& vector) + // numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); + vector& insert_back(const vector& vector) { - return insert_back_range_impl(vector.cbegin(), vector.cend()); + return insert_back_range_impl(vector.begin(), vector.end()); } // Inserts a range of values at the beginning of the vector in place (mutating) // // example: - // functional_vector numbers({ 4, 5, 6 }); - // numbers.insert_front(functional_vector({1, 2, 3})); + // fcpp::vector numbers({ 4, 5, 6 }); + // numbers.insert_front(fcpp::vector({1, 2, 3})); // // outcome: - // numbers -> functional_vector numbers({ 1, 2, 3, 4, 5, 6 }); - functional_vector& insert_front(const functional_vector& vector) + // numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); + vector& insert_front(const vector& vector) { - return insert_front_range_impl(vector.cbegin(), vector.cend()); + 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 functional_vector numbers({ 4, 5, 6 }); - // auto augmented_numbers = numbers.inserting_back(functional_vector({1, 2, 3})); + // const fcpp::vector numbers({ 4, 5, 6 }); + // auto augmented_numbers = numbers.inserting_back(fcpp::vector({1, 2, 3})); // // outcome: - // augmented_numbers -> functional_vector numbers({ 4, 5, 6, 1, 2, 3 }); - [[nodiscard]] functional_vector inserting_back(const functional_vector& vector) const + // 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.cbegin(), vector.cend()); + 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 functional_vector numbers({ 4, 5, 6 }); - // auto augmented_numbers = numbers.inserting_front(functional_vector({1, 2, 3})); + // const fcpp::vector numbers({ 4, 5, 6 }); + // auto augmented_numbers = numbers.inserting_front(fcpp::vector({1, 2, 3})); // // outcome: - // augmented_numbers -> functional_vector numbers({ 1, 2, 3, 4, 5, 6 }); - [[nodiscard]] functional_vector inserting_front(const functional_vector& vector) const + // 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.cbegin(), vector.cend()); + return inserting_front_range_impl(vector.begin(), vector.end()); } // Inserts a range of values at the end of the vector in place (mutating) // // example: - // functional_vector numbers({ 4, 5, 6 }); + // fcpp::vector numbers({ 4, 5, 6 }); // numbers.insert_back(std::vector({1, 2, 3})); // // outcome: - // numbers -> functional_vector numbers({ 4, 5, 6, 1, 2, 3 }); - functional_vector& insert_back(const std::vector& vector) + // 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()); } @@ -1163,12 +1162,12 @@ class functional_vector // Inserts a range of values at the beginning of the vector in place (mutating) // // example: - // functional_vector numbers({ 4, 5, 6 }); + // fcpp::vector numbers({ 4, 5, 6 }); // numbers.insert_front(std::vector({1, 2, 3})); // // outcome: - // numbers -> functional_vector numbers({ 1, 2, 3, 4, 5, 6 }); - functional_vector& insert_front(const std::vector& vector) + // 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()); } @@ -1176,12 +1175,12 @@ class functional_vector // 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 functional_vector numbers({ 4, 5, 6 }); + // const fcpp::vector numbers({ 4, 5, 6 }); // auto augmented_numbers = numbers.inserting_back(std::vector({1, 2, 3})); // // outcome: - // augmented_numbers -> functional_vector numbers({ 4, 5, 6, 1, 2, 3 }); - [[nodiscard]] functional_vector inserting_back(const std::vector& vector) const + // 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()); } @@ -1189,12 +1188,12 @@ class functional_vector // 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 functional_vector numbers({ 4, 5, 6 }); + // const fcpp::vector numbers({ 4, 5, 6 }); // auto augmented_numbers = numbers.inserting_front(std::vector({1, 2, 3})); // // outcome: - // augmented_numbers -> functional_vector numbers({ 1, 2, 3, 4, 5, 6 }); - [[nodiscard]] functional_vector inserting_front(const std::vector& vector) const + // 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()); } @@ -1202,12 +1201,12 @@ class functional_vector // Inserts a range of values at the end of the vector in place (mutating) // // example: - // functional_vector numbers({ 4, 5, 6 }); + // fcpp::vector numbers({ 4, 5, 6 }); // numbers.insert_back(std::initializer_list({1, 2, 3})); // // outcome: - // numbers -> functional_vector numbers({ 4, 5, 6, 1, 2, 3 }); - functional_vector& insert_back(const std::initializer_list& list) + // numbers -> fcpp::vector numbers({ 4, 5, 6, 1, 2, 3 }); + vector& insert_back(const std::initializer_list& list) { return insert_back(std::vector(list)); } @@ -1215,12 +1214,12 @@ class functional_vector // Inserts a range of values at the beginning of the vector in place (mutating) // // example: - // functional_vector numbers({ 4, 5, 6 }); + // fcpp::vector numbers({ 4, 5, 6 }); // numbers.insert_front(std::initializer_list({1, 2, 3})); // // outcome: - // numbers -> functional_vector numbers({ 1, 2, 3, 4, 5, 6 }); - functional_vector& insert_front(const std::initializer_list& list) + // numbers -> fcpp::vector numbers({ 1, 2, 3, 4, 5, 6 }); + vector& insert_front(const std::initializer_list& list) { return insert_front(std::vector(list)); } @@ -1228,12 +1227,12 @@ class functional_vector // 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 functional_vector numbers({ 4, 5, 6 }); + // const fcpp::vector numbers({ 4, 5, 6 }); // auto augmented_numbers = numbers.inserting_back(std::initializer_list({1, 2, 3})); // // outcome: - // augmented_numbers -> functional_vector numbers({ 4, 5, 6, 1, 2, 3 }); - [[nodiscard]] functional_vector inserting_back(const std::initializer_list& list) const + // 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)); } @@ -1241,12 +1240,12 @@ class functional_vector // 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 functional_vector numbers({ 4, 5, 6 }); + // const fcpp::vector numbers({ 4, 5, 6 }); // auto augmented_numbers = numbers.inserting_front(std::initializer_list({1, 2, 3})); // // outcome: - // augmented_numbers -> functional_vector numbers({ 1, 2, 3, 4, 5, 6 }); - [[nodiscard]] functional_vector inserting_front(const std::initializer_list& list) const + // 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)); } @@ -1254,25 +1253,25 @@ class functional_vector // Replaces the existing contents starting at `index` with the contents of the given vector (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // numbers.replace_range_at(4, functional_vector({9, -10, 8})); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // numbers.replace_range_at(4, fcpp::vector({9, -10, 8})); // // outcome: - // numbers -> functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - functional_vector& replace_range_at(int index, const functional_vector& vector) + // 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.cbegin(), vector.cend()); + 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: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // numbers.replace_range_at(4, std::vector({9, -10, 8})); // // outcome: - // numbers -> functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - functional_vector& replace_range_at(int index, const std::vector& vector) + // 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()); } @@ -1280,12 +1279,12 @@ class functional_vector // Replaces the existing contents starting at `index` with the contents of the given vector (mutating) // // example: - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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 -> functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - functional_vector& replace_range_at(int index, const std::initializer_list& list) + // 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)); } @@ -1293,25 +1292,25 @@ class functional_vector // Returns a copy whose elements starting at `index` are replaced with the contents of the given vector (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); - // auto replaced_numbers = numbers.replacing_range_at(4, functional_vector({9, -10, 8})); + // 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 -> functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - [[nodiscard]] functional_vector replacing_range_at(int index, const functional_vector& vector) const + // 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.cbegin(), vector.cend()); + 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 functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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 -> functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - [[nodiscard]] functional_vector replacing_range_at(int index, const std::vector& vector) const + // 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()); } @@ -1319,12 +1318,12 @@ class functional_vector // Returns a copy whose elements starting at `index` are replaced with the contents of the given vector (non-mutating) // // example: - // const functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // 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 -> functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }) - [[nodiscard]] functional_vector replacing_range_at(int index, const std::initializer_list& list) const + // 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)); } @@ -1332,12 +1331,12 @@ class functional_vector // Replaces all existing elements with a constant element (mutating) // // example: - // functional_vector numbers({1, 3, -6, 4, -9}); + // fcpp::vector numbers({1, 3, -6, 4, -9}); // numbers.fill(7); // // outcome: - // numbers -> functional_vector({ 7, 7, 7, 7, 7 }) - functional_vector& fill(const T& element) + // numbers -> fcpp::vector({ 7, 7, 7, 7, 7 }) + vector& fill(const T& element) { std::fill(backing_vector_.begin(), backing_vector_.end(), @@ -1346,33 +1345,33 @@ class functional_vector } // Returns the size of the vector (how many elements it contains, it may be different from its capacity) - size_t size() const + [[nodiscard]] size_t size() const { return backing_vector_.size(); } // Clears the vector by removing all elements (mutating) - functional_vector& clear() + vector& clear() { backing_vector_.clear(); return *this; } // Returns true if the vector has no elements - bool is_empty() const + [[nodiscard]] bool is_empty() const { return backing_vector_.empty(); } // Returns the underlying capacity of the vector, which can be larger from its size - size_t capacity() const + [[nodiscard]] size_t capacity() const { return backing_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 - functional_vector& reserve(size_t count) + vector& reserve(size_t count) { backing_vector_.reserve(count); return *this; @@ -1385,22 +1384,22 @@ class functional_vector // example: // // numbers.capacity() = 9 // // numbers.size() = 9 - // functional_vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); + // fcpp::vector numbers({1, 4, 2, 5, 8, 3, 1, 7, 1}); // // numbers.capacity() = 9 // // numbers.size() = 5 - // // numbers -> functional_vector({1, 4, 2, 5, 8}); + // // numbers -> fcpp::vector({1, 4, 2, 5, 8}); // numbers.resize(5); // // // empty_numbers.capacity() = 0 // // empty_numbers.size() = 0 - // functional_vector empty_numbers; + // fcpp::vector empty_numbers; // // // empty_numbers.capacity() = 5 // // empty_numbers.size() = 5 - // // empty_numbers -> functional_vector({0, 0, 0, 0, 0}); + // // empty_numbers -> fcpp::vector({0, 0, 0, 0, 0}); // empty_numbers.resize(5); - functional_vector& resize(size_t count) + vector& resize(size_t count) { backing_vector_.resize(count); return *this; @@ -1413,7 +1412,7 @@ class functional_vector } // Returns the const begin iterator, useful for other standard library algorithms - [[nodiscard]] typename std::vector::const_iterator cbegin() const + [[nodiscard]] typename std::vector::const_iterator begin() const { return backing_vector_.begin(); } @@ -1425,11 +1424,24 @@ class functional_vector } // Returns the const end iterator, useful for other standard library algorithms - [[nodiscard]] typename std::vector::const_iterator cend() const + [[nodiscard]] typename std::vector::const_iterator end() const { return backing_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) @@ -1447,28 +1459,30 @@ class functional_vector } // Returns true if both instances have equal sizes and the corresponding elements (same index) are equal - bool operator ==(const functional_vector& rhs) const + bool operator ==(const vector& rhs) const { #ifdef CPP17_AVAILABLE - return std::equal(backing_vector_.cbegin(), - backing_vector_.cend(), - rhs.cbegin(), - rhs.cend()); + 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]) { + if (!((*this)[i] == rhs[i])) { return false; } } + return true; #endif } - // Returns false if either the sizes are not equal or at least corresponding element (same index) is not equal - bool operator !=(const functional_vector& rhs) const + // 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); } @@ -1481,7 +1495,7 @@ class functional_vector #else template #endif - functional_vector& insert_back_range_impl(const Iterator& vec_begin, const Iterator& vec_end) + vector& insert_back_range_impl(const Iterator& vec_begin, const Iterator& vec_end) { backing_vector_.insert(backing_vector_.end(), vec_begin, @@ -1494,7 +1508,7 @@ class functional_vector #else template #endif - functional_vector& insert_front_range_impl(const Iterator& vec_begin, const Iterator& vec_end) + vector& insert_front_range_impl(const Iterator& vec_begin, const Iterator& vec_end) { backing_vector_.insert(backing_vector_.begin(), vec_begin, @@ -1507,14 +1521,14 @@ class functional_vector #else template #endif - [[nodiscard]] functional_vector inserting_back_range_impl(const Iterator& vec_begin, const Iterator& vec_end) const + [[nodiscard]] vector inserting_back_range_impl(const Iterator& vec_begin, const Iterator& vec_end) const { auto augmented_vector(backing_vector_); augmented_vector.reserve(augmented_vector.size() + std::distance(vec_begin, vec_end)); augmented_vector.insert(augmented_vector.end(), vec_begin, vec_end); - return functional_vector(augmented_vector); + return vector(augmented_vector); } #ifdef CPP17_AVAILABLE @@ -1522,37 +1536,37 @@ class functional_vector #else template #endif - [[nodiscard]] functional_vector inserting_front_range_impl(const Iterator& vec_begin, const Iterator& vec_end) const + [[nodiscard]] vector inserting_front_range_impl(const Iterator& vec_begin, const Iterator& vec_end) const { auto augmented_vector(backing_vector_); augmented_vector.reserve(augmented_vector.size() + std::distance(vec_begin, vec_end)); augmented_vector.insert(augmented_vector.begin(), vec_begin, vec_end); - return functional_vector(augmented_vector); + return vector(augmented_vector); } #ifdef CPP17_AVAILABLE template::value>> [[nodiscard]] auto zip_impl( const Iterator& vec_begin, const Iterator& vec_end) const -> - functional_vector>> + vector>> { using U = deref_type; #else template - [[nodiscard]] functional_vector> zip_impl(const typename std::vector::const_iterator& vec_begin, + [[nodiscard]] vector> zip_impl(const typename std::vector::const_iterator& vec_begin, const typename std::vector::const_iterator& vec_end) const { #endif const auto vec_size = std::distance(vec_begin, vec_end); assert(backing_vector_.size() == vec_size); - std::vector> combined_vector; + std::vector> combined_vector; combined_vector.reserve(vec_size); for (size_t i = 0; i < vec_size; ++i) { combined_vector.push_back({backing_vector_[i], *(vec_begin + i)}); } - return functional_vector>(std::move(combined_vector)); + return vector>(std::move(combined_vector)); } #ifdef CPP17_AVAILABLE @@ -1561,7 +1575,7 @@ class functional_vector #else template #endif - functional_vector& insert_at_impl(int index, + vector& insert_at_impl(int index, const Iterator& vec_begin, const Iterator& vec_end) { @@ -1580,7 +1594,7 @@ class functional_vector #else template #endif - [[nodiscard]] functional_vector inserting_at_impl(int index, + [[nodiscard]] vector inserting_at_impl(int index, const Iterator& vec_begin, const Iterator& vec_end) const { @@ -1593,7 +1607,7 @@ class functional_vector augmented_vector.insert(augmented_vector.begin() + index, vec_begin, vec_end); - return functional_vector(std::move(augmented_vector)); + return vector(std::move(augmented_vector)); } #ifdef CPP17_AVAILABLE @@ -1601,7 +1615,7 @@ class functional_vector #else template #endif - functional_vector& replace_range_at_imp(int index, + vector& replace_range_at_imp(int index, const Iterator& vec_begin, const Iterator& vec_end) { @@ -1618,7 +1632,7 @@ class functional_vector #else template #endif - [[nodiscard]] functional_vector replacing_range_at_imp(int index, + [[nodiscard]] vector replacing_range_at_imp(int index, const Iterator& vec_begin, const Iterator& vec_end) const { @@ -1628,7 +1642,7 @@ class functional_vector std::copy(vec_begin, vec_end, replaced_vector.begin() + index); - return functional_vector(replaced_vector); + return vector(replaced_vector); } void assert_smaller_size(int index) const @@ -1641,3 +1655,5 @@ class functional_vector assert(index <= size() && index >= 0); } }; + +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9af57e6..82fe24a 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -set (LIBNAME functional_vector) +set (LIBNAME fcpp) # Properties->C/C++->General->Additional Include Directories include_directories ("../include") @@ -24,7 +24,7 @@ target_link_libraries(${LIBNAME} PUBLIC tbb) endif() # creates preprocessor definition used for library exports -add_compile_definitions("FUNCTIONAL_VECTOR_EXPORTS") +add_compile_definitions("FUNCTIONAL_CPP_EXPORTS") set_target_properties(${LIBNAME} PROPERTIES OUTPUT_NAME ${LIBNAME} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0d3a07b..9719af1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,7 +16,7 @@ file (GLOB TEST_SOURCES add_executable (${EXENAME} ${TEST_SOURCES}) # Properties->Linker->Input->Additional Dependencies -target_link_libraries(${EXENAME} PUBLIC functional_vector gtest_main) +target_link_libraries(${EXENAME} PUBLIC fcpp gtest_main) # Creates a folder "executables" and adds target project under it set_property(TARGET ${EXENAME} PROPERTY FOLDER "executables") diff --git a/tests/optional_test.cc b/tests/optional_test.cc index 699f1d1..f2d2b7c 100644 --- a/tests/optional_test.cc +++ b/tests/optional_test.cc @@ -23,6 +23,8 @@ #include #include "optional.h" +using namespace fcpp; + TEST(OptionalTest, InvalidTest) { const optional_t index; EXPECT_FALSE(index.has_value()); diff --git a/tests/set_test.cc b/tests/set_test.cc new file mode 100644 index 0000000..5a72fcc --- /dev/null +++ b/tests/set_test.cc @@ -0,0 +1,545 @@ +// MIT License +// +// Copyright (c) 2022 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 "set.h" +#include "vector.h" +#include "test_types.h" + +using namespace fcpp; + +template +void debug(set& set) +{ + 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]); +} + +TEST(SetTest, EmptyConstructor) +{ + const set set_under_test; + 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(SetTest, StdVectorConstructor) +{ + const set set_under_test(std::vector({1, 5, 3, 3})); + test_contents(set_under_test); +} + +TEST(SetTest, FunctionalVectorConstructor) +{ + const set set_under_test(vector({1, 5, 3, 3})); + 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(SetTest, Subscripting) +{ + const set set_under_test(std::set({1, 5, 3, 3})); + test_contents(set_under_test); +} + +TEST(SetTest, ConstSubscripting) +{ + 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); +} + +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); +} + +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); +} + +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); +} + +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); +} + +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); +} + +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); +} + +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); +} + +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); +} + +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); +} + +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); +} + +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); +} + +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()); +} + +TEST(SetTest, 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(SetTest, MinEmptySet) +{ + 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()); +} + +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; +#if __linux__ // NOLINT(clang-diagnostic-undef) + EXPECT_EQ(person(18, "Jannet"), maximum.value()); +#else + EXPECT_EQ(person(25, "Kate"), maximum.value()); +#endif +} + +TEST(SetTest, MaxEmptySet) +{ + 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); +} + +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; })); +} + +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; })); +} + +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; })); +} + +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); +} + +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); +} + +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); +} + +TEST(SetTest, ZipWithFunctionalSetDifferentSizes) +{ + 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); +} + +TEST(SetTest, ZipWithStdSetDifferentSizes) +{ + 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); +} + +TEST(SetTest, ZipWithFunctionalVectorDifferentSizes) +{ + 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); +} + +TEST(SetTest, ZipWithStdVectorDifferentSizes) +{ + const set ages({ 25, 45, 30, 63 }); + const std::vector persons({ "Jake" }); + EXPECT_DEATH(ages.zip(persons), ""); +} + +TEST(SetTest, RemoveExistingElement) +{ + 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); +} + +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); +} + +TEST(SetTest, InsertNewElement) +{ + 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); +} + +TEST(SetTest, InsertExistingElement) +{ + 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); +} + +TEST(SetTest, Clear) +{ + 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()); +} + +TEST(SetTest, Contains) +{ + 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); +} + +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); +} + +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); +} diff --git a/tests/test_types.h b/tests/test_types.h new file mode 100644 index 0000000..208a4f0 --- /dev/null +++ b/tests/test_types.h @@ -0,0 +1,85 @@ +// MIT License +// +// Copyright (c) 2022 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 + +struct child +{ + child() + : age(0) + { + } + + child(int age) + : age(age) + { + } + + int age; + + bool operator< (const child& other) const { + return age < other.age; + } +}; + +struct child_comparator { + bool operator() (const child& a, const child& b) const { + return a < b; + } +}; + +struct person +{ + person() + : age(0), name("") + { + } + + person(int age, std::string name) + : age(age), name(std::move(name)) + { + } + + int age; + std::string name; + + std::size_t hash() const { + std::size_t h1 = std::hash{}(name); + std::size_t h2 = std::hash{}(age); + return h1 ^ (h2 << 1); + } + + bool operator == (const person& other) const { + return age == other.age && name == other.name; + } + + bool operator< (const person& other) const { + return hash() < other.hash(); + } +}; + +struct person_comparator { + bool operator() (const person& a, const person& b) const { + return a < b; + } +}; diff --git a/tests/functional_vector_test.cc b/tests/vector_test.cc similarity index 50% rename from tests/functional_vector_test.cc rename to tests/vector_test.cc index c18707a..ebd75ca 100644 --- a/tests/functional_vector_test.cc +++ b/tests/vector_test.cc @@ -21,60 +21,26 @@ // SOFTWARE. #include -#include #include -#include "functional_vector.h" +#include "vector.h" +#include "set.h" #include "index_range.h" +#include "test_types.h" +#include "warnings.h" -#ifdef _MSC_VER -#pragma warning(disable: 4834) // discarding return value of function with 'nodiscard' attribute -#pragma warning(disable: 4100) // unreferenced formal parameter -#pragma warning(disable: 4018) // signed/unsigned mismatch -#pragma warning(disable: 4389) // signed/unsigned mismatch -#endif - -struct child -{ - child() - : age(0) - { - } - - child(int age) - : age(age) - { - } - - int age; -}; - -struct person -{ - person() - : age(0), name("") - { - } - - person(int age, std::string name) - : age(age), name(std::move(name)) - { - } - - int age; - std::string name; -}; +using namespace fcpp; template -void debug_vector(const functional_vector& vec) +void debug(const vector& vec) { vec.for_each([](const T& element) { std::cout << element << std::endl; }); } -TEST(FunctionalVectorTest, InsertBackTest) +TEST(VectorTest, InsertBack) { - functional_vector vector_under_test; + vector vector_under_test; EXPECT_EQ(0, vector_under_test.size()); vector_under_test.insert_back(5); @@ -87,9 +53,9 @@ TEST(FunctionalVectorTest, InsertBackTest) EXPECT_EQ(-1, vector_under_test[1]); } -TEST(FunctionalVectorTest, InsertFrontTest) +TEST(VectorTest, InsertFront) { - functional_vector vector_under_test; + vector vector_under_test; EXPECT_EQ(0, vector_under_test.size()); vector_under_test.insert_front(5); @@ -102,119 +68,119 @@ TEST(FunctionalVectorTest, InsertFrontTest) EXPECT_EQ(5, vector_under_test[1]); } -TEST(FunctionalVectorTest, InsertingBackTest) +TEST(VectorTest, InsertingBack) { - const functional_vector vector_under_test({3, 6, 2, 8}); + 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(functional_vector({ 3, 6, 2, 8, 5 }), vector_new_instance); + EXPECT_EQ(vector({ 3, 6, 2, 8, 5 }), vector_new_instance); } -TEST(FunctionalVectorTest, InsertingFrontTest) +TEST(VectorTest, InsertingFront) { - const functional_vector vector_under_test({3, 6, 2, 8}); + 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(functional_vector({ 5, 3, 6, 2, 8}), vector_new_instance); + EXPECT_EQ(vector({ 5, 3, 6, 2, 8}), vector_new_instance); } -TEST(FunctionalVectorTest, InsertBackFromFunctionalVectorTest) +TEST(VectorTest, InsertBackFromFunctionalVector) { - functional_vector vector_under_test({ 4, 5, 6 }); - vector_under_test.insert_back(functional_vector({1, 2, 3})); - EXPECT_EQ(functional_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(FunctionalVectorTest, InsertBackFromStdVectorTest) +TEST(VectorTest, InsertBackFromStdVector) { - functional_vector vector_under_test({ 4, 5, 6 }); + vector vector_under_test({ 4, 5, 6 }); vector_under_test.insert_back(std::vector{ 1, 2, 3 }); - EXPECT_EQ(functional_vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertBackFromInitializerListTest) +TEST(VectorTest, InsertBackFromInitializerList) { - functional_vector vector_under_test({ 4, 5, 6 }); + vector vector_under_test({ 4, 5, 6 }); vector_under_test.insert_back(std::initializer_list{ 1, 2, 3 }); - EXPECT_EQ(functional_vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertFrontFromFunctionalVectorTest) +TEST(VectorTest, InsertFrontFromFunctionalVector) { - functional_vector vector_under_test({ 4, 5, 6 }); - vector_under_test.insert_front(functional_vector({1, 2, 3})); - EXPECT_EQ(functional_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(FunctionalVectorTest, InsertFrontFromStdVectorTest) +TEST(VectorTest, InsertFrontFromStdVector) { - functional_vector vector_under_test({ 4, 5, 6 }); + vector vector_under_test({ 4, 5, 6 }); vector_under_test.insert_front(std::vector{ 1, 2, 3 }); - EXPECT_EQ(functional_vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertFrontFromInitializerListTest) +TEST(VectorTest, InsertFrontFromInitializerList) { - functional_vector vector_under_test({ 4, 5, 6 }); + vector vector_under_test({ 4, 5, 6 }); vector_under_test.insert_front(std::initializer_list{ 1, 2, 3 }); - EXPECT_EQ(functional_vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertingBackFromFunctionalVectorTest) +TEST(VectorTest, InsertingBackFromFunctionalVector) { - const functional_vector vector_under_test({ 4, 5, 6 }); - const auto vector_new_instance = vector_under_test.inserting_back(functional_vector({1, 2, 3})); - EXPECT_EQ(functional_vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(functional_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(FunctionalVectorTest, InsertingBackFromStdVectorTest) +TEST(VectorTest, InsertingBackFromStdVector) { - const functional_vector vector_under_test({ 4, 5, 6 }); + 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(functional_vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(functional_vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); } -TEST(FunctionalVectorTest, InsertingBackFromInitializerListTest) +TEST(VectorTest, InsertingBackFromInitializerList) { - const functional_vector vector_under_test({ 4, 5, 6 }); + 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(functional_vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(functional_vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 4, 5, 6, 1, 2, 3 }), vector_new_instance); } -TEST(FunctionalVectorTest, InsertingFrontFromFunctionalVectorTest) +TEST(VectorTest, InsertingFrontFromFunctionalVector) { - const functional_vector vector_under_test({ 4, 5, 6 }); - const auto vector_new_instance = vector_under_test.inserting_front(functional_vector({1, 2, 3})); - EXPECT_EQ(functional_vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(functional_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(FunctionalVectorTest, InsertingFrontFromStdVectorTest) +TEST(VectorTest, InsertingFrontFromStdVector) { - const functional_vector vector_under_test({ 4, 5, 6 }); + 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(functional_vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(functional_vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); } -TEST(FunctionalVectorTest, InsertingFrontFromInitializerListTest) +TEST(VectorTest, InsertingFrontFromInitializerList) { - const functional_vector vector_under_test({ 4, 5, 6 }); + 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(functional_vector({ 4, 5, 6 }), vector_under_test); - EXPECT_EQ(functional_vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); + EXPECT_EQ(vector({ 4, 5, 6 }), vector_under_test); + EXPECT_EQ(vector({ 1, 2, 3, 4, 5, 6 }), vector_new_instance); } -TEST(FunctionalVectorTest, MapTest) +TEST(VectorTest, Map) { - const functional_vector vector_under_test({1, 3, 4}); + const vector vector_under_test({1, 3, 4}); const auto mapped_vector = vector_under_test.map([](const int& age) { return child(age); }); @@ -225,9 +191,9 @@ TEST(FunctionalVectorTest, MapTest) } #ifdef PARALLEL_ALGORITHM_AVAILABLE -TEST(FunctionalVectorTest, MapParallelTest) +TEST(VectorTest, MapParallel) { - const functional_vector vector_under_test({1, 3, 4}); + const vector vector_under_test({1, 3, 4}); const auto mapped_vector = vector_under_test.map_parallel([](const int& age) { return child(age); }); @@ -238,9 +204,9 @@ TEST(FunctionalVectorTest, MapParallelTest) } #endif -TEST(FunctionalVectorTest, FilterTest) +TEST(VectorTest, Filter) { - functional_vector vector_under_test({child(1), child(3), child(4)}); + vector vector_under_test({child(1), child(3), child(4)}); vector_under_test.filter([](const child& child) { return child.age < 2; }); @@ -253,9 +219,9 @@ TEST(FunctionalVectorTest, FilterTest) } #ifdef PARALLEL_ALGORITHM_AVAILABLE -TEST(FunctionalVectorTest, FilterParallelTest) +TEST(VectorTest, FilterParallel) { - functional_vector vector_under_test({child(1), child(3), child(4)}); + vector vector_under_test({child(1), child(3), child(4)}); vector_under_test.filter_parallel([](const child& child) { return child.age < 2; }); @@ -268,9 +234,9 @@ TEST(FunctionalVectorTest, FilterParallelTest) } #endif -TEST(FunctionalVectorTest, FilteredTest) +TEST(VectorTest, Filtered) { - const functional_vector vector_under_test({child(1), child(3), child(4)}); + 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; }); @@ -280,9 +246,9 @@ TEST(FunctionalVectorTest, FilteredTest) } #ifdef PARALLEL_ALGORITHM_AVAILABLE -TEST(FunctionalVectorTest, FilteredParallelTest) +TEST(VectorTest, FilteredParallel) { - const functional_vector vector_under_test({child(1), child(3), child(4)}); + 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; }); @@ -292,9 +258,9 @@ TEST(FunctionalVectorTest, FilteredParallelTest) } #endif -TEST(FunctionalVectorTest, ReverseTest) +TEST(VectorTest, Reverse) { - functional_vector vector_under_test({child(6), child(2), child(9)}); + 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); @@ -302,9 +268,9 @@ TEST(FunctionalVectorTest, ReverseTest) EXPECT_EQ(6, vector_under_test[2].age); } -TEST(FunctionalVectorTest, ReversedTest) +TEST(VectorTest, Reversed) { - const functional_vector vector_under_test({child(6), child(2), child(9)}); + 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); @@ -317,23 +283,23 @@ TEST(FunctionalVectorTest, ReversedTest) EXPECT_EQ(9, vector_under_test[2].age); } -TEST(FunctionalVectorTest, ZipWithStdVectorUnequalSizesThrowsTest) +TEST(VectorTest, ZipWithStdVectorUnequalSizesThrows) { - const functional_vector ages_vector({32, 25, 53, 62}); + const vector ages_vector({32, 25, 53, 62}); EXPECT_DEATH({ const auto zipped_vector = ages_vector.zip(std::vector({"Jake", "Mary"})); }, ""); } -TEST(FunctionalVectorTest, ZipWithFunctionalVectorUnequalSizesThrowsTest) +TEST(VectorTest, ZipWithFunctionalVectorUnequalSizesThrows) { - const functional_vector ages_vector({32, 25, 53, 62}); - const auto names_vector = functional_vector({"Jake", "Mary"}); + 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(FunctionalVectorTest, ZipWithFunctionalVectorTest) +TEST(VectorTest, ZipWithFunctionalVector) { - const functional_vector ages_vector({32, 25, 53}); - const functional_vector names_vector({"Jake", "Mary", "John"}); + 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()); @@ -347,9 +313,9 @@ TEST(FunctionalVectorTest, ZipWithFunctionalVectorTest) EXPECT_EQ("John", zipped_vector[2].second); } -TEST(FunctionalVectorTest, ZipWithStdVectorTest) +TEST(VectorTest, ZipWithStdVector) { - const functional_vector ages_vector({32, 25, 53}); + 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()); @@ -363,9 +329,9 @@ TEST(FunctionalVectorTest, ZipWithStdVectorTest) EXPECT_EQ("John", zipped_vector[2].second); } -TEST(FunctionalVectorTest, ZipWithInitializerListTest) +TEST(VectorTest, ZipWithInitializerList) { - const functional_vector ages_vector({32, 25, 53}); + 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()); @@ -379,9 +345,9 @@ TEST(FunctionalVectorTest, ZipWithInitializerListTest) EXPECT_EQ("John", zipped_vector[2].second); } -TEST(FunctionalVectorTest, SortTest) +TEST(VectorTest, Sort) { - functional_vector vector_under_test({ + 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) @@ -403,9 +369,9 @@ TEST(FunctionalVectorTest, SortTest) EXPECT_EQ(52, vector_under_test[3].age); } -TEST(FunctionalVectorTest, SortedTest) +TEST(VectorTest, Sorted) { - const functional_vector vector_under_test({ + 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) { @@ -433,9 +399,9 @@ TEST(FunctionalVectorTest, SortedTest) EXPECT_EQ(52, sorted_vector[3].age); } -TEST(FunctionalVectorTest, SortAscendingTest) +TEST(VectorTest, SortAscending) { - functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -444,9 +410,9 @@ TEST(FunctionalVectorTest, SortAscendingTest) EXPECT_EQ(9, vector_under_test[3]); } -TEST(FunctionalVectorTest, SortedAscendingTest) +TEST(VectorTest, SortedAscending) { - const functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -461,9 +427,9 @@ TEST(FunctionalVectorTest, SortedAscendingTest) EXPECT_EQ(9, sorted_vector[3]); } -TEST(FunctionalVectorTest, SortDescendingTest) +TEST(VectorTest, SortDescending) { - functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -472,9 +438,9 @@ TEST(FunctionalVectorTest, SortDescendingTest) EXPECT_EQ(-4, vector_under_test[3]); } -TEST(FunctionalVectorTest, SortedDescendingTest) +TEST(VectorTest, SortedDescending) { - const functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -490,9 +456,9 @@ TEST(FunctionalVectorTest, SortedDescendingTest) } #ifdef PARALLEL_ALGORITHM_AVAILABLE -TEST(FunctionalVectorTest, SortParallelTest) +TEST(VectorTest, SortParallel) { - functional_vector vector_under_test({ + 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){ @@ -513,9 +479,9 @@ TEST(FunctionalVectorTest, SortParallelTest) EXPECT_EQ(52, vector_under_test[3].age); } -TEST(FunctionalVectorTest, SortedParallelTest) +TEST(VectorTest, SortedParallel) { - const functional_vector vector_under_test({ + 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){ @@ -543,9 +509,9 @@ TEST(FunctionalVectorTest, SortedParallelTest) EXPECT_EQ(52, sorted_vector[3].age); } -TEST(FunctionalVectorTest, SortAscendingParallelTest) +TEST(VectorTest, SortAscendingParallel) { - functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -554,9 +520,9 @@ TEST(FunctionalVectorTest, SortAscendingParallelTest) EXPECT_EQ(9, vector_under_test[3]); } -TEST(FunctionalVectorTest, SortedAscendingParallelTest) +TEST(VectorTest, SortedAscendingParallel) { - const functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -571,9 +537,9 @@ TEST(FunctionalVectorTest, SortedAscendingParallelTest) EXPECT_EQ(9, sorted_vector[3]); } -TEST(FunctionalVectorTest, SortDescendingParallelTest) +TEST(VectorTest, SortDescendingParallel) { - functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -582,9 +548,9 @@ TEST(FunctionalVectorTest, SortDescendingParallelTest) EXPECT_EQ(-4, vector_under_test[3]); } -TEST(FunctionalVectorTest, SortedDescendingParallelTest) +TEST(VectorTest, SortedDescendingParallel) { - const functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -600,45 +566,45 @@ TEST(FunctionalVectorTest, SortedDescendingParallelTest) } #endif -TEST(FunctionalVectorTest, SubscriptOperatorNegativeDeathTest) +TEST(VectorTest, SubscriptOperatorNegativeDeath) { - const functional_vector vector_under_test({3, 1, 9, -4}); + const vector vector_under_test({3, 1, 9, -4}); EXPECT_DEATH(vector_under_test[-1], ""); } -TEST(FunctionalVectorTest, SubscriptOperatorIndexEqualToSizeDeathTest) +TEST(VectorTest, SubscriptOperatorIndexEqualToSizeDeath) { - const functional_vector vector_under_test({3, 1, 9, -4}); + const vector vector_under_test({3, 1, 9, -4}); EXPECT_DEATH(vector_under_test[4], ""); } -TEST(FunctionalVectorTest, SubscriptOperatorIndexLargerThanSizeDeathTest) +TEST(VectorTest, SubscriptOperatorIndexLargerThanSizeDeath) { - const functional_vector vector_under_test({3, 1, 9, -4}); + const vector vector_under_test({3, 1, 9, -4}); EXPECT_DEATH(vector_under_test[5], ""); } -TEST(FunctionalVectorTest, SubscriptOperatorAssignNegativeDeathTest) +TEST(VectorTest, SubscriptOperatorAssignNegativeDeath) { - functional_vector vector_under_test({3, 1, 9, -4}); + vector vector_under_test({3, 1, 9, -4}); EXPECT_DEATH(vector_under_test[-1] = 5, ""); } -TEST(FunctionalVectorTest, SubscriptOperatorAssignIndexEqualSizeDeathTest) +TEST(VectorTest, SubscriptOperatorAssignIndexEqualSizeDeath) { - functional_vector vector_under_test({3, 1, 9, -4}); + vector vector_under_test({3, 1, 9, -4}); EXPECT_DEATH(vector_under_test[4] = 5, ""); } -TEST(FunctionalVectorTest, SubscriptOperatorAssignIndexLargerThanSizeDeathTest) +TEST(VectorTest, SubscriptOperatorAssignIndexLargerThanSizeDeath) { - functional_vector vector_under_test({3, 1, 9, -4}); + vector vector_under_test({3, 1, 9, -4}); EXPECT_DEATH(vector_under_test[5] = -3, ""); } -TEST(FunctionalVectorTest, SubscriptOperatorAssignTest) +TEST(VectorTest, SubscriptOperatorAssign) { - functional_vector vector_under_test({3, 1, 9, -4}); + 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]); @@ -647,173 +613,173 @@ TEST(FunctionalVectorTest, SubscriptOperatorAssignTest) EXPECT_EQ(-4, vector_under_test[3]); } -TEST(FunctionalVectorTest, FindFirstIndexEmptyVectorTest) +TEST(VectorTest, FindFirstIndexEmptyVector) { - const functional_vector vector_under_test; + const vector vector_under_test; EXPECT_FALSE(vector_under_test.find_first_index(-3).has_value()); } -TEST(FunctionalVectorTest, FindFirstIndexFilledVectorWithoutMatchTest) +TEST(VectorTest, FindFirstIndexFilledVectorWithoutMatch) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, FindFirstIndexFilledVectorTest) +TEST(VectorTest, FindFirstIndexFilledVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, FindLastIndexEmptyVectorTest) +TEST(VectorTest, FindLastIndexEmptyVector) { - const functional_vector vector_under_test; + const vector vector_under_test; EXPECT_FALSE(vector_under_test.find_last_index(-3).has_value()); } -TEST(FunctionalVectorTest, FindLastIndexFilledVectorWithoutMatchTest) +TEST(VectorTest, FindLastIndexFilledVectorWithoutMatch) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, FindLastIndexFilledVectorTest) +TEST(VectorTest, FindLastIndexFilledVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, FindAllIndicesEmptyVectorTest) +TEST(VectorTest, FindAllIndicesEmptyVector) { - const functional_vector vector_under_test; + const vector vector_under_test; EXPECT_EQ(0, vector_under_test.find_all_indices(-3).size()); } -TEST(FunctionalVectorTest, FindAllIndicesFilledVectorWithoutMatchTest) +TEST(VectorTest, FindAllIndicesFilledVectorWithoutMatch) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, FindAllIndicesFilledVectorTest) +TEST(VectorTest, FindAllIndicesFilledVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 9, 1}); + 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(FunctionalVectorTest, RemoveAtEmptyVectorTest) +TEST(VectorTest, RemoveAtEmptyVector) { - functional_vector vector_under_test; + 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(FunctionalVectorTest, RemoveAtFilledVectorAboveSizeTest) +TEST(VectorTest, RemoveAtFilledVectorAboveSize) { - auto vector_under_test = functional_vector({1, 4, 2, 5, 8, 3, 1, 7, 1}); + auto vector_under_test = vector({1, 4, 2, 5, 8, 3, 1, 7, 1}); EXPECT_DEATH(vector_under_test.remove_at(15), ""); } -TEST(FunctionalVectorTest, RemoveAtFilledVectorTest) +TEST(VectorTest, RemoveAtFilledVector) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); vector_under_test.remove_at(1); - EXPECT_EQ(functional_vector({ 1, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); vector_under_test.remove_at(1); - EXPECT_EQ(functional_vector({ 1, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 5, 8, 3, 1, 7, 1 }), vector_under_test); vector_under_test.remove_at(4); - EXPECT_EQ(functional_vector({ 1, 5, 8, 3, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 5, 8, 3, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, RemovingAtEmptyVectorTest) +TEST(VectorTest, RemovingAtEmptyVector) { - const functional_vector vector_under_test; + 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(FunctionalVectorTest, RemovingAtFilledVectorAboveSizeTest) +TEST(VectorTest, RemovingAtFilledVectorAboveSize) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + const vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); EXPECT_DEATH(vector_under_test.removing_at(15), ""); } -TEST(FunctionalVectorTest, RemovingAtFilledVectorTest) +TEST(VectorTest, RemovingAtFilledVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 2, 5, 8, 3, 1, 7, 1 }), shorter_vector); - EXPECT_EQ(functional_vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + 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(FunctionalVectorTest, RemoveBackTest) +TEST(VectorTest, RemoveBack) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); vector_under_test.remove_back(); - EXPECT_EQ(functional_vector({ 1, 4, 2, 5, 8, 3, 1, 7 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7 }), vector_under_test); vector_under_test.remove_back(); - EXPECT_EQ(functional_vector({ 1, 4, 2, 5, 8, 3, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1 }), vector_under_test); vector_under_test.remove_back(); - EXPECT_EQ(functional_vector({ 1, 4, 2, 5, 8, 3 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3 }), vector_under_test); } -TEST(FunctionalVectorTest, RemovingBackTest) +TEST(VectorTest, RemovingBack) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 5, 8, 3, 1, 7 }), vector_without_last_element); - EXPECT_EQ(functional_vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + 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(FunctionalVectorTest, RemoveFrontTest) +TEST(VectorTest, RemoveFront) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); vector_under_test.remove_front(); - EXPECT_EQ(functional_vector({ 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); vector_under_test.remove_front(); - EXPECT_EQ(functional_vector({ 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); vector_under_test.remove_front(); - EXPECT_EQ(functional_vector({ 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 5, 8, 3, 1, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, RemovingFrontTest) +TEST(VectorTest, RemovingFront) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 4, 2, 5, 8, 3, 1, 7, 1 }), vector_without_first_element); - EXPECT_EQ(functional_vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + 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(FunctionalVectorTest, InsertAtEmptyVectorTest) +TEST(VectorTest, InsertAtEmptyVector) { - functional_vector vector_under_test; + 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(FunctionalVectorTest, InsertAtFilledVectorTest) +TEST(VectorTest, InsertAtFilledVector) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 18, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 18, 5, 8, 3, 1, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertingAtEmptyVectorTest) +TEST(VectorTest, InsertingAtEmptyVector) { - const functional_vector vector_under_test; + 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()); @@ -821,359 +787,414 @@ TEST(FunctionalVectorTest, InsertingAtEmptyVectorTest) EXPECT_EQ(0, vector_under_test.size()); } -TEST(FunctionalVectorTest, InsertingAtFilledVectorTest) +TEST(VectorTest, InsertingAtFilledVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 18, 5, 8, 3, 1, 7, 1 }), augmented_vector); - EXPECT_EQ(functional_vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + 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(FunctionalVectorTest, InsertRangeEmptyFunctionalVectorTest) +TEST(VectorTest, InsertRangeEmptyFunctionalVector) { - functional_vector vector_under_test; - const functional_vector vector_to_insert({4, 7, 3, -5}); + vector vector_under_test; + const vector vector_to_insert({4, 7, 3, -5}); vector_under_test.insert_at(0, vector_to_insert); - EXPECT_EQ(functional_vector({ 4, 7, 3, -5 }), vector_under_test); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertRangeExistingWrongInsertionIndexFunctionalVectorTest) +TEST(VectorTest, InsertRangeExistingWrongInsertionIndexFunctionalVector) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const functional_vector vector_to_insert({9, -5, 6}); + 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(FunctionalVectorTest, InsertRangeExistingFunctionalVectorTest) +TEST(VectorTest, InsertRangeExistingFunctionalVector) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const functional_vector vector_to_insert({9, -5, 6}); + 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(functional_vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertRangeEmptyStdVectorTest) +TEST(VectorTest, InsertRangeEmptyStdVector) { - functional_vector 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(functional_vector({ 4, 7, 3, -5 }), vector_under_test); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertRangeExistingWrongInsertionIndexStdVectorTest) +TEST(VectorTest, InsertRangeExistingWrongInsertionIndexStdVector) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, InsertRangeExistingStdVectorTest) +TEST(VectorTest, InsertRangeExistingStdVector) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertRangeEmptyInitializerListTest) +TEST(VectorTest, InsertRangeEmptyInitializerList) { - functional_vector vector_under_test; + vector vector_under_test; vector_under_test.insert_at(0, {4, 7, 3, -5}); - EXPECT_EQ(functional_vector({ 4, 7, 3, -5 }), vector_under_test); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertRangeExistingWrongInsertionIndexInitializerListTest) +TEST(VectorTest, InsertRangeExistingWrongInsertionIndexInitializerList) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, InsertRangeExistingInitializerListTest) +TEST(VectorTest, InsertRangeExistingInitializerList) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); vector_under_test.insert_at(3, {9, -5, 6}); - EXPECT_EQ(functional_vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, InsertingRangeEmptyFunctionalVectorTest) +TEST(VectorTest, InsertingRangeEmptyFunctionalVector) { - const functional_vector vector_under_test; - const functional_vector vector_to_insert({4, 7, 3, -5}); + 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(functional_vector({ 4, 7, 3, -5 }), result_vector); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); } -TEST(FunctionalVectorTest, InsertingRangeExistingWrongInsertionIndexFunctionalVectorTest) +TEST(VectorTest, InsertingRangeExistingWrongInsertionIndexFunctionalVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const functional_vector vector_to_insert({9, -5, 6}); + 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(FunctionalVectorTest, InsertingRangeExistingFunctionalVectorTest) +TEST(VectorTest, InsertingRangeExistingFunctionalVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const functional_vector vector_to_insert({9, -5, 6}); + 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(functional_vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); } -TEST(FunctionalVectorTest, InsertingRangeEmptyStdVectorTest) +TEST(VectorTest, InsertingRangeEmptyStdVector) { - const functional_vector vector_under_test; + 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(functional_vector({ 4, 7, 3, -5 }), result_vector); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); } -TEST(FunctionalVectorTest, InsertingRangeExistingWrongInsertionIndexStdVectorTest) +TEST(VectorTest, InsertingRangeExistingWrongInsertionIndexStdVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, InsertingRangeExistingStdVectorTest) +TEST(VectorTest, InsertingRangeExistingStdVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); } -TEST(FunctionalVectorTest, InsertingRangeEmptyInitializerListTest) +TEST(VectorTest, InsertingRangeEmptyInitializerList) { - const functional_vector vector_under_test; + const vector vector_under_test; const auto result_vector = vector_under_test.inserting_at(0, {4, 7, 3, -5}); - EXPECT_EQ(functional_vector({ 4, 7, 3, -5 }), result_vector); + EXPECT_EQ(vector({ 4, 7, 3, -5 }), result_vector); } -TEST(FunctionalVectorTest, InsertingRangeExistingWrongInsertionIndexInitializerListTest) +TEST(VectorTest, InsertingRangeExistingWrongInsertionIndexInitializerList) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, InsertingRangeExistingInitializerListTest) +TEST(VectorTest, InsertingRangeExistingInitializerList) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); + EXPECT_EQ(vector({ 1, 4, 2, 9, -5, 6, 5, 8, 3, 1, 7, 1 }), result_vector); } -TEST(FunctionalVectorTest, RemoveIndexRangeWithInvalidRangeTest) +TEST(VectorTest, RemoveIndexRangeWithInvalidRange) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); vector_under_test.remove_range(index_range::invalid); - EXPECT_EQ(functional_vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, RemoveIndexRangeEmptyVectorTest) +TEST(VectorTest, RemoveIndexRangeEmptyVector) { - functional_vector vector_under_test; + vector vector_under_test; vector_under_test.remove_range(index_range::start_count(1, 12)); - EXPECT_EQ(functional_vector(), vector_under_test); + EXPECT_EQ(vector(), vector_under_test); } -TEST(FunctionalVectorTest, RemoveIndexRangeStartCountSuccessTest) +TEST(VectorTest, RemoveIndexRangeStartCountSuccess) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 3, 1, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 3, 1, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, RemoveRangeStartEndSuccessTest) +TEST(VectorTest, RemoveRangeStartEndSuccess) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, RemovingIndexRangeWithInvalidRangeTest) +TEST(VectorTest, RemovingIndexRangeWithInvalidRange) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), shorter_vector); + EXPECT_EQ(vector({ 1, 4, 2, 5, 8, 3, 1, 7, 1 }), shorter_vector); } -TEST(FunctionalVectorTest, RemovingRangeEmptyVectorTest) +TEST(VectorTest, RemovingRangeEmptyVector) { - const functional_vector vector_under_test; + const vector vector_under_test; const auto shorter_vector = vector_under_test.removing_range(index_range::start_count(1, 12)); - EXPECT_EQ(functional_vector(), shorter_vector); + EXPECT_EQ(vector(), shorter_vector); } -TEST(FunctionalVectorTest, RemovingIndexRangeStartCountSuccessTest) +TEST(VectorTest, RemovingIndexRangeStartCountSuccess) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 3, 1, 7, 1 }), shorter_vector); + EXPECT_EQ(vector({ 1, 4, 3, 1, 7, 1 }), shorter_vector); } -TEST(FunctionalVectorTest, RemovingIndexRangeStartEndSuccessTest) +TEST(VectorTest, RemovingIndexRangeStartEndSuccess) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 7, 1 }), shorter_vector); + EXPECT_EQ(vector({ 1, 4, 2, 7, 1 }), shorter_vector); } -TEST(FunctionalVectorTest, ReplaceRangeAtWithEmptySource) +TEST(VectorTest, ReplaceRangeAtWithEmptySource) { - functional_vector vector_under_test({5, -3, 4, -9}); + vector vector_under_test({5, -3, 4, -9}); vector_under_test.replace_range_at(3, std::vector()); - EXPECT_EQ(functional_vector({ 5, -3 , 4, -9 }), vector_under_test); + EXPECT_EQ(vector({ 5, -3 , 4, -9 }), vector_under_test); } -TEST(FunctionalVectorTest, ReplaceRangeAtWrongIndex) +TEST(VectorTest, ReplaceRangeAtWrongIndex) { - functional_vector vector_under_test({5, -3, 4, -9}); + 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(FunctionalVectorTest, ReplaceRangeAtMoreElementsInSourceThanCapacityTest) +TEST(VectorTest, ReplaceRangeAtMoreElementsInSourceThanCapacity) { - functional_vector vector_under_test({5, -3, 4, -9}); + 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(FunctionalVectorTest, ReplaceRangeAtWithFunctionalVectorTest) +TEST(VectorTest, ReplaceRangeAtWithFunctionalVector) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - vector_under_test.replace_range_at(4, functional_vector({9, -10, 8})); - EXPECT_EQ(functional_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(FunctionalVectorTest, ReplaceRangeAtWithStdVectorTest) +TEST(VectorTest, ReplaceRangeAtWithStdVector) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, ReplaceRangeAtWithInitializerListTest) +TEST(VectorTest, ReplaceRangeAtWithInitializerList) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), vector_under_test); } -TEST(FunctionalVectorTest, ReplacingRangeAtWithEmptySource) +TEST(VectorTest, ReplacingRangeAtWithEmptySource) { - const functional_vector vector_under_test({5, -3, 4, -9}); + const vector vector_under_test({5, -3, 4, -9}); const auto replaced_vector = vector_under_test.replacing_range_at(3, std::vector()); - EXPECT_EQ(functional_vector({ 5, -3 , 4, -9 }), replaced_vector); + EXPECT_EQ(vector({ 5, -3 , 4, -9 }), replaced_vector); } -TEST(FunctionalVectorTest, ReplacingRangeAtWrongIndex) +TEST(VectorTest, ReplacingRangeAtWrongIndex) { - const functional_vector vector_under_test({5, -3, 4, -9}); + 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(FunctionalVectorTest, ReplacingRangeAtMoreElementsInSourceThanCapacityTest) +TEST(VectorTest, ReplacingRangeAtMoreElementsInSourceThanCapacity) { - const functional_vector vector_under_test({5, -3, 4, -9}); + 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(FunctionalVectorTest, ReplacingRangeAtWithFunctionalVectorTest) +TEST(VectorTest, ReplacingRangeAtWithFunctionalVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); - const auto replaced_vector = vector_under_test.replacing_range_at(4, functional_vector({9, -10, 8})); - EXPECT_EQ(functional_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(FunctionalVectorTest, ReplacingRangeAtWithStdVectorTest) +TEST(VectorTest, ReplacingRangeAtWithStdVector) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); } -TEST(FunctionalVectorTest, ReplacingRangeAtWithInitializerListTest) +TEST(VectorTest, ReplacingRangeAtWithInitializerList) { - const functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); + EXPECT_EQ(vector({ 1, 4, 2, 5, 9, -10, 8, 7, 1 }), replaced_vector); } -TEST(FunctionalVectorTest, FillTest) +TEST(VectorTest, Fill) { - functional_vector vector_under_test({1, 3, -6, 4, -9}); + vector vector_under_test({1, 3, -6, 4, -9}); vector_under_test.fill(7); - EXPECT_EQ(functional_vector({ 7, 7, 7, 7, 7 }), vector_under_test); + EXPECT_EQ(vector({ 7, 7, 7, 7, 7 }), vector_under_test); } -TEST(FunctionalVectorTest, RepeatingConstructorTest) +TEST(VectorTest, RepeatingConstructor) { - const functional_vector vector_under_test(3, "John"); - EXPECT_EQ(functional_vector({ "John", "John", "John" }), vector_under_test); + const vector vector_under_test(3, "John"); + EXPECT_EQ(vector({ "John", "John", "John" }), vector_under_test); } -TEST(FunctionalVectorTest, EqualityOperatorEmptyVectorsTest) +TEST(VectorTest, EqualityOperatorEmptyVectors) { - const functional_vector vec1; - const functional_vector vec2; + const vector vec1; + const vector vec2; EXPECT_TRUE(vec1 == vec2); EXPECT_FALSE(vec1 != vec2); } -TEST(FunctionalVectorTest, EqualityOperatorUnequalSizesTest) +TEST(VectorTest, EqualityOperatorUnequalSizes) { - const functional_vector vec1({1, 2, 3}); - const functional_vector vec2({1, 2, 3, 4}); + const vector vec1({1, 2, 3}); + const vector vec2({1, 2, 3, 4}); EXPECT_TRUE(vec1 != vec2); EXPECT_FALSE(vec1 == vec2); } -TEST(FunctionalVectorTest, EqualityOperatorEqualSizesDifferentElementsTest) +TEST(VectorTest, EqualityOperatorEqualSizesDifferentElements) { - const functional_vector vec1({1, 2, 3}); - const functional_vector vec2({1, 2, 4}); + const vector vec1({1, 2, 3}); + const vector vec2({1, 2, 4}); EXPECT_TRUE(vec1 != vec2); EXPECT_FALSE(vec1 == vec2); } -TEST(FunctionalVectorTest, EqualityOperatorEqualVectorsTest) +TEST(VectorTest, EqualityOperatorEqualVectors) +{ + const vector vec1({1, 2, 3}); + const vector vec2({1, 2, 3}); + EXPECT_TRUE(vec1 == vec2); + EXPECT_FALSE(vec1 != vec2); +} + +TEST(VectorTest, EqualityOperatorCustomTypeEqualVectors) { - const functional_vector vec1({1, 2, 3}); - const functional_vector vec2({1, 2, 3}); + const vector vec1({ + 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); } -TEST(FunctionalVectorTest, ClearEmptyVectorTest) +TEST(VectorTest, EqualityOperatorCustomTypeUnequalSizes) { - functional_vector vector_under_test; + 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); +} + +TEST(VectorTest, EqualityOperatorCustomTypeUnequalVectors) +{ + const vector vec1({ + person(15, "Jake"), + person(18, "Jannet"), + person(25, "Kate") + }); + + const vector vec2({ + person(15, "Jake"), + person(53, "Bob"), + person(35, "Suzan") + }); + + 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()); } -TEST(FunctionalVectorTest, ClearFilledVectorTest) +TEST(VectorTest, ClearFilledVector) { - functional_vector vector_under_test({5, -3, 4, -9}); + 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(FunctionalVectorTest, CapacityReserveClearTest) +TEST(VectorTest, CapacityReserveClear) { - functional_vector vector_under_test; + vector vector_under_test; EXPECT_EQ(0, vector_under_test.capacity()); EXPECT_EQ(0, vector_under_test.size()); @@ -1190,36 +1211,36 @@ TEST(FunctionalVectorTest, CapacityReserveClearTest) EXPECT_EQ(0, vector_under_test.size()); } -TEST(FunctionalVectorTest, ResizeEmptyVectorTest) +TEST(VectorTest, ResizeEmptyVector) { - functional_vector vector_under_test; + vector vector_under_test; vector_under_test.resize(5); - EXPECT_EQ(functional_vector({ 0, 0, 0, 0, 0 }), vector_under_test); + 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(FunctionalVectorTest, ResizeSmallerThanCurrentSizeTest) +TEST(VectorTest, ResizeSmallerThanCurrentSize) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(functional_vector({1, 4, 2, 5, 8}), vector_under_test); + 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(FunctionalVectorTest, AllOfFalseTest) +TEST(VectorTest, AllOfFalse) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, AllOfTrueTest) +TEST(VectorTest, AllOfTrue) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); vector_under_test.all_of([](const int& number) { return number < 10; }); @@ -1227,15 +1248,15 @@ TEST(FunctionalVectorTest, AllOfTrueTest) } #ifdef PARALLEL_ALGORITHM_AVAILABLE -TEST(FunctionalVectorTest, AllOfParallelFalseTest) +TEST(VectorTest, AllOfParallelFalse) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, AllOfParallelTrueTest) +TEST(VectorTest, AllOfParallelTrue) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); vector_under_test.all_of([](const int& number) { return number < 10; }); @@ -1243,63 +1264,93 @@ TEST(FunctionalVectorTest, AllOfParallelTrueTest) } #endif -TEST(FunctionalVectorTest, AnyOfFalseTest) +TEST(VectorTest, AnyOfFalse) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, AnyOfTrueTest) +TEST(VectorTest, AnyOfTrue) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, AnyOfParallelFalseTest) +TEST(VectorTest, AnyOfParallelFalse) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, AnyOfParallelTrueTest) +TEST(VectorTest, AnyOfParallelTrue) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, NoneOfFalseTest) +TEST(VectorTest, NoneOfFalse) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, NoneOfTrueTest) +TEST(VectorTest, NoneOfTrue) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, NoneOfParallelFalseTest) +TEST(VectorTest, NoneOfParallelFalse) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, NoneOfParallelTrueTest) +TEST(VectorTest, NoneOfParallelTrue) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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(FunctionalVectorTest, ForEachParallelTest) +TEST(VectorTest, ForEachParallel) { - functional_vector vector_under_test({1, 4, 2, 5, 8, 3, 1, 7, 1}); + 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); +} + +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); +} diff --git a/tests/warnings.h b/tests/warnings.h new file mode 100644 index 0000000..85046f9 --- /dev/null +++ b/tests/warnings.h @@ -0,0 +1,30 @@ +// MIT License +// +// Copyright (c) 2022 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 + +#ifdef _MSC_VER +#pragma warning(disable: 4834) // discarding return value of function with 'nodiscard' attribute +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4018) // signed/unsigned mismatch +#pragma warning(disable: 4389) // signed/unsigned mismatch +#endif