From 5287fe4b3b9f58330881d2a62abf6ce8e1159b8d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 8 Jul 2026 09:06:50 +0100 Subject: [PATCH] Allow etl::vector to store pointers to functions and member functions (#1492) * Refactored vector.h Deleted ivectorpointer.h * Minor changes * Fixed code incompatible with C++03 * Clang-format changes * Removed redundant double-qualified name * Fixed is_is_object_pointer_v to is_object_pointer_v * Added new test files to meson.build * Added overflow checks to vector_ext copy and move constructors and assignments Added assert throw tests. * Added diagnostic pushes to eliminate GCC warning false positives * Changed the GCC C++23 Github action to use GCC14 * Applied clang-format * Added guard to pop_heap * Added guard to adjust_heap * Attempt to fix GCC diagnostic * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * clang-format * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Missing newline at end of file * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic Re-enable ranges algorithm tests * Attempt to fix GCC diagnostic * clang-format * Changed gcc --version to gcc-14 --version --------- Co-authored-by: John Wellbelove Co-authored-by: Roland Reichwein --- .github/workflows/gcc-c++23.yml | 32 +- docs/types/type-traits.md | 19 +- include/etl/algorithm.h | 19 +- include/etl/intrusive_avl_tree.h | 2 + include/etl/private/ivectorpointer.h | 1140 -------------- include/etl/span.h | 10 +- include/etl/type_traits.h | 93 +- include/etl/vector.h | 902 +++++++---- test/CMakeLists.txt | 4 + test/meson.build | 4 + test/test_circular_iterator.cpp | 2 + test/test_deque.cpp | 4 + test/test_map.cpp | 4 + test/test_variant_variadic.cpp | 16 +- test/test_vector.cpp | 30 +- test/test_vector_external_buffer.cpp | 18 + test/test_vector_function_pointer.cpp | 1321 ++++++++++++++++ ...ector_function_pointer_external_buffer.cpp | 1301 ++++++++++++++++ test/test_vector_member_function_pointer.cpp | 1330 +++++++++++++++++ ...ember_function_pointer_external_buffer.cpp | 1329 ++++++++++++++++ test/vs2022/etl.vcxproj | 18 +- test/vs2022/etl.vcxproj.filters | 57 +- 22 files changed, 6117 insertions(+), 1538 deletions(-) delete mode 100644 include/etl/private/ivectorpointer.h create mode 100644 test/test_vector_function_pointer.cpp create mode 100644 test/test_vector_function_pointer_external_buffer.cpp create mode 100644 test/test_vector_member_function_pointer.cpp create mode 100644 test/test_vector_member_function_pointer_external_buffer.cpp diff --git a/.github/workflows/gcc-c++23.yml b/.github/workflows/gcc-c++23.yml index 9ca6baf0..842b6152 100644 --- a/.github/workflows/gcc-c++23.yml +++ b/.github/workflows/gcc-c++23.yml @@ -21,12 +21,12 @@ jobs: - name: Build run: | export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - export CC=gcc - export CXX=g++ + export CC=gcc-14 + export CXX=g++-14 cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./ - gcc --version + gcc-14 --version make -j "$(getconf _NPROCESSORS_ONLN)" - + - name: Run tests run: ./test/etl_tests -v @@ -43,12 +43,12 @@ jobs: - name: Build run: | export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - export CC=gcc - export CXX=g++ + export CC=gcc-14 + export CXX=g++-14 cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./ - gcc --version + gcc-14 --version make -j "$(getconf _NPROCESSORS_ONLN)" - + - name: Run tests run: ./test/etl_tests -v @@ -65,10 +65,10 @@ jobs: - name: Build run: | export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - export CC=gcc - export CXX=g++ + export CC=gcc-14 + export CXX=g++-14 cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./ - gcc --version + gcc-14 --version make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests @@ -87,11 +87,11 @@ jobs: - name: Build run: | export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - export CC=gcc - export CXX=g++ + export CC=gcc-14 + export CXX=g++-14 cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 -DETL_OPTIMISATION=-O3 ./ - gcc --version + gcc-14 --version make -j "$(getconf _NPROCESSORS_ONLN)" - + - name: Run tests - run: ./test/etl_tests -v \ No newline at end of file + run: ./test/etl_tests -v diff --git a/docs/types/type-traits.md b/docs/types/type-traits.md index 6bd1fcaa..721fdfc3 100644 --- a/docs/types/type-traits.md +++ b/docs/types/type-traits.md @@ -3,7 +3,7 @@ title: "type_traits" --- Reverse engineered types traits classes from C++11 plus several ETL extensions. -This file is generated from type_traits_generator.h. See Generators +This file is generated from `type_traits_generator.h`. See Generators Not all traits have been defined as some rely on compiler intrinsics that are not available on all compiler platforms. `integral_constant` @@ -459,3 +459,20 @@ template class Template> inline constexpr bool is_specialization_v = etl::is_specialization::value; ``` C++17 + +## is_object_pointer +From: `20.49.0` + +```cpp +template +struct is_object_pointer +``` +Checks if `T` is a pointer to an object. +Pointers to functions and member functions return `false`. +The result is found in the member `value`. + +```cpp +template +inline constexpr bool is_object_pointer_v = etl::is_object_pointer::value; +``` +C++17 diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 1c544b40..7e4bfd72 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -914,6 +914,7 @@ namespace etl TDistance top_index = value_index; TDistance child2nd = (2 * value_index) + 2; +#include "etl/private/diagnostic_array_bounds_push.h" while (child2nd < length) { if (compare(*(first + child2nd), *(first + (child2nd - 1)))) @@ -931,6 +932,7 @@ namespace etl *(first + value_index) = ETL_MOVE(*(first + (child2nd - 1))); value_index = child2nd - 1; } +#include "etl/private/diagnostic_pop.h" push_heap(first, value_index, top_index, ETL_MOVE(value), compare); } @@ -965,6 +967,12 @@ namespace etl typedef typename etl::iterator_traits::value_type value_t; typedef typename etl::iterator_traits::difference_type distance_t; + const distance_t n = last - first; + if (n <= 1) + { + return; + } + value_t value = ETL_MOVE(*(last - 1)); *(last - 1) = ETL_MOVE(*first); @@ -5844,6 +5852,8 @@ namespace etl { ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "partial_sort requires random access iterators"); + #include "etl/private/diagnostic_array_bounds_push.h" + I last_it = ranges::next(first, last); if (first == middle || first == last_it) @@ -5880,6 +5890,8 @@ namespace etl } return last_it; + + #include "etl/private/diagnostic_pop.h" } template >> @@ -5933,6 +5945,8 @@ namespace etl { ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "partial_sort_copy requires the output to be random access iterators"); + #include "etl/private/diagnostic_array_bounds_push.h" + I1 in_last = ranges::next(first, last); I2 out_last = ranges::next(result_first, result_last); @@ -5970,7 +5984,6 @@ namespace etl } } - #include "etl/private/diagnostic_array_bounds_push.h" // Sort the heap to produce a sorted output range for (auto heap_end = heap_size - 1; heap_end > 0; --heap_end) { @@ -7025,6 +7038,8 @@ namespace etl { ETL_STATIC_ASSERT(etl::is_random_access_iterator::value, "pop_heap requires random access iterators"); + #include "etl/private/diagnostic_array_bounds_push.h" + I last_it = ranges::next(first, last); auto length = etl::distance(first, last_it); @@ -7041,6 +7056,8 @@ namespace etl sift_down(first, decltype(length)(0), etl::distance(first, last_it), comp, proj); return ranges::next(first, last); + + #include "etl/private/diagnostic_pop.h" } template >> diff --git a/include/etl/intrusive_avl_tree.h b/include/etl/intrusive_avl_tree.h index ff92935c..bb278500 100644 --- a/include/etl/intrusive_avl_tree.h +++ b/include/etl/intrusive_avl_tree.h @@ -227,11 +227,13 @@ namespace etl return ETL_NULLPTR == base::etl_parent; } +#include "private/diagnostic_null_dereference_push.h" ETL_NODISCARD link_type* get_parent() { return static_cast(base::etl_parent); } +#include "private/diagnostic_pop.h" ETL_NODISCARD const link_type* get_parent() const diff --git a/include/etl/private/ivectorpointer.h b/include/etl/private/ivectorpointer.h deleted file mode 100644 index c28bab62..00000000 --- a/include/etl/private/ivectorpointer.h +++ /dev/null @@ -1,1140 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2016 John Wellbelove - -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. -******************************************************************************/ - -#ifndef ETL_IVECTOR_POINTER_INCLUDED -#define ETL_IVECTOR_POINTER_INCLUDED - -#ifndef ETL_IN_VECTOR_H - #error This header is a private element of etl::ivector -#endif - -#include "pvoidvector.h" - -namespace etl -{ - //*************************************************************************** - /// The base class for specifically sized vectors. - /// Can be used as a reference type for all vectors containing a specific - /// pointer type. - ///\ingroup vector - //*************************************************************************** - template - class ivector : public pvoidvector - { - public: - - typedef T* value_type; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type* iterator; - typedef const value_type* const_iterator; - typedef ETL_OR_STD::reverse_iterator reverse_iterator; - typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; - typedef size_t size_type; - typedef typename etl::iterator_traits::difference_type difference_type; - - protected: - - typedef value_type parameter_t; - - private: - - typedef pvoidvector base_t; - - template - struct is_compatible_iterator - : etl::integral_constant::value_type>::value - && etl::is_convertible::value_type, value_type>::value> - { - }; - - public: - - //********************************************************************* - /// Returns an iterator to the beginning of the vector. - ///\return An iterator to the beginning of the vector. - //********************************************************************* - iterator begin() - { - return iterator(base_t::begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the vector. - ///\return A const iterator to the beginning of the vector. - //********************************************************************* - const_iterator begin() const - { - return const_iterator(base_t::begin()); - } - - //********************************************************************* - /// Returns an iterator to the end of the vector. - ///\return An iterator to the end of the vector. - //********************************************************************* - iterator end() - { - return iterator(base_t::end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the vector. - ///\return A const iterator to the end of the vector. - //********************************************************************* - const_iterator end() const - { - return const_iterator(base_t::end()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the vector. - ///\return A const iterator to the beginning of the vector. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator(base_t::cbegin()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the vector. - ///\return A const iterator to the end of the vector. - //********************************************************************* - const_iterator cend() const - { - return const_iterator(base_t::cend()); - } - - //********************************************************************* - /// Returns an reverse iterator to the reverse beginning of the vector. - ///\return Iterator to the reverse beginning of the vector. - //********************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(iterator(base_t::end())); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the vector. - ///\return Const iterator to the reverse beginning of the vector. - //********************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(const_iterator(base_t::end())); - } - - //********************************************************************* - /// Returns a reverse iterator to the end + 1 of the vector. - ///\return Reverse iterator to the end + 1 of the vector. - //********************************************************************* - reverse_iterator rend() - { - return reverse_iterator(iterator(base_t::begin())); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the vector. - ///\return Const reverse iterator to the end + 1 of the vector. - //********************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(const_iterator(base_t::begin())); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the vector. - ///\return Const reverse iterator to the reverse beginning of the vector. - //********************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(const_iterator(base_t::cend())); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the vector. - ///\return Const reverse iterator to the end + 1 of the vector. - //********************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(const_iterator(base_t::cbegin())); - } - - //********************************************************************* - /// Resizes the vector. - /// If asserts or exceptions are enabled and the new size is larger than the - /// maximum then a vector_full is thrown. - ///\param new_size The new size. - //********************************************************************* - void resize(size_t new_size) - { - base_t::resize(new_size); - } - - //********************************************************************* - /// Resizes the vector. - /// If asserts or exceptions are enabled and the new size is larger than the - /// maximum then a vector_full is thrown. - ///\param new_size The new size. - ///\param value The value to fill new elements with. Default = default - /// constructed value. - //********************************************************************* - void resize(size_t new_size, value_type value) - { - base_t::resize(new_size, value); - } - - //********************************************************************* - /// Resizes the vector, but does not initialise new entries. - ///\param new_size The new size. - //********************************************************************* - void uninitialized_resize(size_t new_size) - { - base_t::uninitialized_resize(new_size); - } - - //********************************************************************* - /// Returns a reference to the value at index 'i' - ///\param i The index. - ///\return A reference to the value at index 'i' - //********************************************************************* - reference operator[](size_t i) - { - return reference(base_t::operator[](i)); - } - - //********************************************************************* - /// Returns a const reference to the value at index 'i' - ///\param i The index. - ///\return A const reference to the value at index 'i' - //********************************************************************* - const_reference operator[](size_t i) const - { - return const_reference(base_t::operator[](i)); - } - - //********************************************************************* - /// Returns a reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds - /// if the index is out of range. - ///\param i The index. - ///\return A reference to the value at index 'i' - //********************************************************************* - reference at(size_t i) - { - return reference(base_t::at(i)); - } - - //********************************************************************* - /// Returns a const reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds - /// if the index is out of range. - ///\param i The index. - ///\return A const reference to the value at index 'i' - //********************************************************************* - const_reference at(size_t i) const - { - return const_reference(base_t::at(i)); - } - - //********************************************************************* - /// Returns a reference to the first element. - ///\return A reference to the first element. - //********************************************************************* - reference front() - { - return reference(base_t::front()); - } - - //********************************************************************* - /// Returns a const reference to the first element. - ///\return A const reference to the first element. - //********************************************************************* - const_reference front() const - { - return const_reference(base_t::front()); - } - - //********************************************************************* - /// Returns a reference to the last element. - ///\return A reference to the last element. - //********************************************************************* - reference back() - { - return reference(base_t::back()); - } - - //********************************************************************* - /// Returns a const reference to the last element. - ///\return A const reference to the last element. - //********************************************************************* - const_reference back() const - { - return const_reference(base_t::back()); - } - - //********************************************************************* - /// Returns a pointer to the beginning of the vector data. - ///\return A pointer to the beginning of the vector data. - //********************************************************************* - pointer data() - { - return pointer(base_t::data()); - } - - //********************************************************************* - /// Returns a const pointer to the beginning of the vector data. - ///\return A const pointer to the beginning of the vector data. - //********************************************************************* - const_pointer data() const - { - return const_pointer(base_t::data()); - } - - //********************************************************************* - /// Assigns values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector - /// does not have enough free space. If asserts or exceptions are enabled, - /// emits vector_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - typename etl::enable_if< is_compatible_iterator::value, void>::type assign(TIterator first, TIterator last) - { - base_t::assign(first, last); - } - - //********************************************************************* - /// Assigns values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector - /// does not have enough free space. - ///\param n The number of elements to add. - ///\param value The value to insert for each element. - //********************************************************************* - void assign(size_t n, parameter_t value) - { - base_t::assign(n, value); - } - - //************************************************************************* - /// Clears the vector. - //************************************************************************* - void clear() - { - base_t::clear(); - } - - //********************************************************************* - /// Inserts a value at the end of the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector is - /// already full. - ///\param value The value to add. - //********************************************************************* - void push_back(parameter_t value) - { - base_t::push_back(value); - } - - //********************************************************************* - /// Constructs a value at the end of the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector is - /// already full. - ///\param value The value to add. - //********************************************************************* - reference emplace_back() - { - base_t::emplace_back(ETL_NULLPTR); - - return back(); - } - - //********************************************************************* - /// Constructs a value at the end of the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector is - /// already full. - ///\param value The value to add. - //********************************************************************* - reference emplace_back(parameter_t value) - { - base_t::emplace_back(value); - - return back(); - } - - //************************************************************************* - /// Removes an element from the end of the vector. - /// Does nothing if the vector is empty. - //************************************************************************* - void pop_back() - { - base_t::pop_back(); - } - - //********************************************************************* - /// Inserts a value to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector is - /// already full. - ///\param position The position to insert before. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator position, parameter_t value) - { - return iterator(base_t::insert(base_t::iterator(position), value)); - } - - //************************************************************************* - /// Emplaces a value to the vector at the specified position. - //************************************************************************* - iterator emplace(const_iterator position) - { - return iterator(base_t::emplace(base_t::iterator(position), ETL_NULLPTR)); - } - - //************************************************************************* - /// Emplaces a value to the vector at the specified position. - //************************************************************************* - iterator emplace(const_iterator position, parameter_t value) - { - return iterator(base_t::emplace(base_t::iterator(position), value)); - } - - //********************************************************************* - /// Inserts 'n' values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector - /// does not have enough free space. - ///\param position The position to insert before. - ///\param n The number of elements to add. - ///\param value The value to insert. - //********************************************************************* - void insert(const_iterator position, size_t n, parameter_t value) - { - base_t::insert(base_t::iterator(position), n, value); - } - - //********************************************************************* - /// Inserts a range of values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector - /// does not have enough free space. - ///\param position The position to insert before. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - typename etl::enable_if< is_compatible_iterator::value, void>::type insert(const_iterator position, TIterator first, TIterator last) - { - base_t::insert(base_t::iterator(position), first, last); - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - ///\return An iterator pointing to the element that followed the erased - /// element. - //********************************************************************* - iterator erase(iterator i_element) - { - return iterator(base_t::erase(base_t::iterator(i_element))); - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - ///\return An iterator pointing to the element that followed the erased - /// element. - //********************************************************************* - iterator erase(const_iterator i_element) - { - return iterator(base_t::erase(base_t::const_iterator(i_element))); - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including - /// the element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - ///\return An iterator pointing to the element that followed the erased - /// element. - //********************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - return iterator(base_t::erase(base_t::const_iterator(first), base_t::const_iterator(last))); - } - - //********************************************************************* - /// Swap contents with another vector. Performs operation on each - /// individual element. - ///\param other The other vector to swap with. - //********************************************************************* - void swap(ivector& other) - { - if (this == &other) - { - return; - } - - ETL_ASSERT_OR_RETURN(this->max_size() >= other.size() && other.max_size() >= this->size(), ETL_ERROR(vector_full)); - - ivector& smaller = other.size() > this->size() ? *this : other; - ivector& larger = other.size() > this->size() ? other : *this; - - etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); - - typename ivector::iterator larger_itr = etl::next(larger.begin(), static_cast(smaller.size())); - - etl::move(larger_itr, larger.end(), etl::back_inserter(smaller)); - - larger.erase(larger_itr, larger.end()); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - ivector& operator=(const ivector& rhs) - { - base_t::operator=(rhs); - - return *this; - } - -#if ETL_USING_CPP11 - //************************************************************************* - /// Move assignment operator. - //************************************************************************* - ivector& operator=(ivector&& rhs) - { - (void)base_t::operator=(etl::move(rhs)); - - return *this; - } -#endif - -#ifdef ETL_IVECTOR_REPAIR_ENABLE - //************************************************************************* - /// Fix the internal pointers after a low level memory copy. - //************************************************************************* - virtual void repair() = 0; -#endif - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - ivector(T** p_buffer_, size_t MAX_SIZE_) - : pvoidvector(reinterpret_cast(p_buffer_), MAX_SIZE_) - { - } - }; - - template - class ivector : public pvoidvector - { - public: - - typedef const T* value_type; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type* iterator; - typedef const value_type* const_iterator; - typedef ETL_OR_STD::reverse_iterator reverse_iterator; - typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; - typedef size_t size_type; - typedef typename etl::iterator_traits::difference_type difference_type; - - protected: - - typedef value_type parameter_t; - - private: - - typedef pvoidvector base_t; - - template - struct is_compatible_iterator - : etl::integral_constant::value_type>::value - && etl::is_convertible::value_type, value_type>::value> - { - }; - - public: - - //********************************************************************* - /// Returns an iterator to the beginning of the vector. - ///\return An iterator to the beginning of the vector. - //********************************************************************* - iterator begin() - { - return iterator(base_t::begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the vector. - ///\return A const iterator to the beginning of the vector. - //********************************************************************* - const_iterator begin() const - { - return const_iterator(base_t::begin()); - } - - //********************************************************************* - /// Returns an iterator to the end of the vector. - ///\return An iterator to the end of the vector. - //********************************************************************* - iterator end() - { - return iterator(base_t::end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the vector. - ///\return A const iterator to the end of the vector. - //********************************************************************* - const_iterator end() const - { - return const_iterator(base_t::end()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the vector. - ///\return A const iterator to the beginning of the vector. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator(base_t::cbegin()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the vector. - ///\return A const iterator to the end of the vector. - //********************************************************************* - const_iterator cend() const - { - return const_iterator(base_t::cend()); - } - - //********************************************************************* - /// Returns an reverse iterator to the reverse beginning of the vector. - ///\return Iterator to the reverse beginning of the vector. - //********************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(iterator(base_t::end())); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the vector. - ///\return Const iterator to the reverse beginning of the vector. - //********************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(const_iterator(base_t::end())); - } - - //********************************************************************* - /// Returns a reverse iterator to the end + 1 of the vector. - ///\return Reverse iterator to the end + 1 of the vector. - //********************************************************************* - reverse_iterator rend() - { - return reverse_iterator(iterator(base_t::begin())); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the vector. - ///\return Const reverse iterator to the end + 1 of the vector. - //********************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(const_iterator(base_t::begin())); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the vector. - ///\return Const reverse iterator to the reverse beginning of the vector. - //********************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(const_iterator(base_t::cend())); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the vector. - ///\return Const reverse iterator to the end + 1 of the vector. - //********************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(const_iterator(base_t::cbegin())); - } - - //********************************************************************* - /// Resizes the vector. - /// If asserts or exceptions are enabled and the new size is larger than the - /// maximum then a vector_full is thrown. - ///\param new_size The new size. - //********************************************************************* - void resize(size_t new_size) - { - base_t::resize(new_size); - } - - //********************************************************************* - /// Resizes the vector. - /// If asserts or exceptions are enabled and the new size is larger than the - /// maximum then a vector_full is thrown. - ///\param new_size The new size. - ///\param value The value to fill new elements with. Default = default - /// constructed value. - //********************************************************************* - void resize(size_t new_size, value_type value) - { - base_t::resize(new_size, const_cast(value)); - } - - //********************************************************************* - /// Resizes the vector, but does not initialise new entries. - ///\param new_size The new size. - //********************************************************************* - void uninitialized_resize(size_t new_size) - { - base_t::uninitialized_resize(new_size); - } - - //********************************************************************* - /// Returns a reference to the value at index 'i' - ///\param i The index. - ///\return A reference to the value at index 'i' - //********************************************************************* - reference operator[](size_t i) - { - return reference(base_t::operator[](i)); - } - - //********************************************************************* - /// Returns a const reference to the value at index 'i' - ///\param i The index. - ///\return A const reference to the value at index 'i' - //********************************************************************* - const_reference operator[](size_t i) const - { - return const_reference(base_t::operator[](i)); - } - - //********************************************************************* - /// Returns a reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds - /// if the index is out of range. - ///\param i The index. - ///\return A reference to the value at index 'i' - //********************************************************************* - reference at(size_t i) - { - return reference(base_t::at(i)); - } - - //********************************************************************* - /// Returns a const reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds - /// if the index is out of range. - ///\param i The index. - ///\return A const reference to the value at index 'i' - //********************************************************************* - const_reference at(size_t i) const - { - return const_reference(base_t::at(i)); - } - - //********************************************************************* - /// Returns a reference to the first element. - ///\return A reference to the first element. - //********************************************************************* - reference front() - { - return reference(base_t::front()); - } - - //********************************************************************* - /// Returns a const reference to the first element. - ///\return A const reference to the first element. - //********************************************************************* - const_reference front() const - { - return const_reference(base_t::front()); - } - - //********************************************************************* - /// Returns a reference to the last element. - ///\return A reference to the last element. - //********************************************************************* - reference back() - { - return reference(base_t::back()); - } - - //********************************************************************* - /// Returns a const reference to the last element. - ///\return A const reference to the last element. - //********************************************************************* - const_reference back() const - { - return const_reference(base_t::back()); - } - - //********************************************************************* - /// Returns a pointer to the beginning of the vector data. - ///\return A pointer to the beginning of the vector data. - //********************************************************************* - pointer data() - { - return pointer(base_t::data()); - } - - //********************************************************************* - /// Returns a const pointer to the beginning of the vector data. - ///\return A const pointer to the beginning of the vector data. - //********************************************************************* - const_pointer data() const - { - return const_pointer(base_t::data()); - } - - //********************************************************************* - /// Assigns values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector - /// does not have enough free space. If asserts or exceptions are enabled, - /// emits vector_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - typename etl::enable_if< is_compatible_iterator::value, void>::type assign(TIterator first, TIterator last) - { - base_t::assign(first, last); - } - - //********************************************************************* - /// Assigns values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector - /// does not have enough free space. - ///\param n The number of elements to add. - ///\param value The value to insert for each element. - //********************************************************************* - void assign(size_t n, parameter_t value) - { - base_t::assign(n, const_cast(value)); - } - - //************************************************************************* - /// Clears the vector. - //************************************************************************* - void clear() - { - base_t::clear(); - } - - //********************************************************************* - /// Inserts a value at the end of the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector is - /// already full. - ///\param value The value to add. - //********************************************************************* - void push_back(parameter_t value) - { - base_t::push_back(const_cast(value)); - } - - //************************************************************************* - /// Removes an element from the end of the vector. - /// Does nothing if the vector is empty. - //************************************************************************* - void pop_back() - { - base_t::pop_back(); - } - - //********************************************************************* - /// Inserts a value to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector is - /// already full. - ///\param position The position to insert before. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator position, parameter_t value) - { - return iterator(base_t::insert(base_t::iterator(position), const_cast(value))); - } - - //********************************************************************* - /// Inserts 'n' values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector - /// does not have enough free space. - ///\param position The position to insert before. - ///\param n The number of elements to add. - ///\param value The value to insert. - //********************************************************************* - void insert(const_iterator position, size_t n, parameter_t value) - { - base_t::insert(base_t::iterator(position), n, const_cast(value)); - } - - //********************************************************************* - /// Inserts a range of values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector - /// does not have enough free space. - ///\param position The position to insert before. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - typename etl::enable_if< is_compatible_iterator::value, void>::type insert(const_iterator position, TIterator first, TIterator last) - { - base_t::insert(base_t::iterator(position), first, last); - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - ///\return An iterator pointing to the element that followed the erased - /// element. - //********************************************************************* - iterator erase(iterator i_element) - { - return iterator(base_t::erase(base_t::iterator(i_element))); - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - ///\return An iterator pointing to the element that followed the erased - /// element. - //********************************************************************* - iterator erase(const_iterator i_element) - { - return iterator(base_t::erase(base_t::iterator(i_element))); - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including - /// the element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - ///\return An iterator pointing to the element that followed the erased - /// element. - //********************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - return iterator(base_t::erase(base_t::iterator(first), base_t::iterator(last))); - } - - //********************************************************************* - /// Swap contents with another vector. Performs operation on each - /// individual element. - ///\param other The other vector to swap with. - //********************************************************************* - void swap(ivector& other) - { - if (this == &other) - { - return; - } - - ETL_ASSERT_OR_RETURN(this->max_size() >= other.size() && other.max_size() >= this->size(), ETL_ERROR(vector_full)); - - ivector& smaller = other.size() > this->size() ? *this : other; - ivector& larger = other.size() > this->size() ? other : *this; - - etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); - - typename ivector::iterator larger_itr = etl::next(larger.begin(), static_cast(smaller.size())); - - etl::move(larger_itr, larger.end(), etl::back_inserter(smaller)); - - larger.erase(larger_itr, larger.end()); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - ivector& operator=(const ivector& rhs) - { - base_t::operator=(rhs); - - return *this; - } - -#if ETL_USING_CPP11 - //************************************************************************* - /// Move assignment operator. - //************************************************************************* - ivector& operator=(ivector&& rhs) - { - (void)base_t::operator=(etl::move(rhs)); - - return *this; - } -#endif - -#ifdef ETL_IVECTOR_REPAIR_ENABLE - //************************************************************************* - /// Fix the internal pointers after a low level memory copy. - //************************************************************************* - virtual void repair() = 0; -#endif - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - ivector(const T** p_buffer_, size_t MAX_SIZE_) - : pvoidvector(reinterpret_cast(const_cast(p_buffer_)), MAX_SIZE_) - { - } - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the arrays are equal, otherwise false - ///\ingroup vector - //*************************************************************************** - template - bool operator==(const etl::ivector& lhs, const etl::ivector& rhs) - { - return pvoidvector_equal(lhs, rhs); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup vector - //*************************************************************************** - template - bool operator!=(const etl::ivector& lhs, const etl::ivector& rhs) - { - return pvoidvector_not_equal(lhs, rhs); - } - - //*************************************************************************** - /// Less than operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the first vector is lexicographically less than the - /// second, otherwise false \ingroup vector - //*************************************************************************** - template - bool operator<(const etl::ivector& lhs, const etl::ivector& rhs) - { - return pvoidvector_less_than(lhs, rhs); - } - - //*************************************************************************** - /// Greater than operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the first vector is lexicographically greater than - /// the second, otherwise false \ingroup vector - //*************************************************************************** - template - bool operator>(const etl::ivector& lhs, const etl::ivector& rhs) - { - return pvoidvector_greater_than(lhs, rhs); - } - - //*************************************************************************** - /// Less than or equal operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the first vector is lexicographically less than or - /// equal to the second, otherwise - ///< b>false \ingroup vector - //*************************************************************************** - template - bool operator<=(const etl::ivector& lhs, const etl::ivector& rhs) - { - return pvoidvector_less_than_equal(lhs, rhs); - } - - //*************************************************************************** - /// Greater than or equal operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the first vector is lexicographically greater than - /// or equal to the second, otherwise - ///< b>false \ingroup vector - //*************************************************************************** - template - bool operator>=(const etl::ivector& lhs, const etl::ivector& rhs) - { - return pvoidvector_greater_than_equal(lhs, rhs); - } - - //*************************************************************************** - // Helper functions - //*************************************************************************** - inline bool pvoidvector_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs) - { - return operator==(lhs, rhs); - } - - inline bool pvoidvector_not_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs) - { - return operator!=(lhs, rhs); - } - - inline bool pvoidvector_less_than(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs) - { - return operator<(lhs, rhs); - } - - inline bool pvoidvector_greater_than(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs) - { - return operator>(lhs, rhs); - } - - inline bool pvoidvector_less_than_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs) - { - return operator<=(lhs, rhs); - } - - inline bool pvoidvector_greater_than_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs) - { - return operator>=(lhs, rhs); - } -} // namespace etl - -#endif diff --git a/include/etl/span.h b/include/etl/span.h index 3288fc35..1724a87d 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -1491,14 +1491,14 @@ namespace etl span(const etl::array&) -> span; // Forward declaration of etl::ivector - template + template class ivector; - template - span(etl::ivector&) -> span; + template + span(etl::ivector&) -> span; - template - span(const etl::ivector&) -> span; + template + span(const etl::ivector&) -> span; #if ETL_USING_STL && ETL_USING_CPP11 template diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 6f3b21bd..52fd9859 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -1144,8 +1144,8 @@ namespace etl inline constexpr bool is_class_v = is_class::value; #endif - //*************************************************************************** - /// is_base_of + //*************************************************************************** + /// is_base_of #if ETL_USING_CPP11 namespace private_type_traits { @@ -1358,9 +1358,9 @@ namespace etl }; #endif - //*************************************************************************** - /// is_convertible - ///\ingroup type_traits + //*************************************************************************** + /// is_convertible + ///\ingroup type_traits #if ETL_USING_CPP11 namespace private_type_traits { @@ -2149,9 +2149,9 @@ namespace etl #endif - //*************************************************************************** - /// is_convertible - ///\ingroup type_traits + //*************************************************************************** + /// is_convertible + ///\ingroup type_traits #if ETL_USING_CPP11 template struct is_convertible : std::is_convertible @@ -3909,6 +3909,32 @@ namespace etl #endif } + //*************************************************************************** + /// Is T a member pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct is_member_pointer_helper : etl::false_type + { + }; + + template + struct is_member_pointer_helper : etl::true_type + { + }; + } // namespace private_type_traits + + template + struct is_member_pointer : private_type_traits::is_member_pointer_helper< typename etl::remove_cv::type> + { + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_pointer_v = etl::is_member_pointer::value; +#endif + #if ETL_USING_CPP11 //********************************* /// Check if T is a function type @@ -4008,6 +4034,15 @@ namespace etl inline constexpr bool is_function_v = etl::is_function::value; #endif +#else + + template + struct is_function : etl::bool_constant::value && !etl::is_const::value && !etl::is_reference::value> + { + }; + +#endif + //*************************************************************************** /// is_object //*************************************************************************** @@ -4016,10 +4051,22 @@ namespace etl { }; - #if ETL_USING_CPP17 +#if ETL_USING_CPP17 template inline constexpr bool is_object_v = etl::is_object::value; - #endif +#endif + + //*************************************************************************** + /// is_object_pointer + //*************************************************************************** + template + struct is_object_pointer : etl::bool_constant::value && etl::is_object::type>::value> + { + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_object_pointer_v = etl::is_object_pointer::value; #endif #if ETL_USING_CPP11 @@ -4075,32 +4122,6 @@ namespace etl #endif #endif - //*************************************************************************** - /// Is T a member pointer - //*************************************************************************** - namespace private_type_traits - { - template - struct is_member_pointer_helper : etl::false_type - { - }; - - template - struct is_member_pointer_helper : etl::true_type - { - }; - } // namespace private_type_traits - - template - struct is_member_pointer : private_type_traits::is_member_pointer_helper< typename etl::remove_cv::type> - { - }; - -#if ETL_USING_CPP17 - template - inline constexpr bool is_member_pointer_v = etl::is_member_pointer::value; -#endif - #if ETL_USING_CPP11 //*************************************************************************** /// Is T a member function pointer diff --git a/include/etl/vector.h b/include/etl/vector.h index 016171b2..492247be 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -46,6 +46,8 @@ SOFTWARE. #include "placement_new.h" #include "static_assert.h" #include "type_traits.h" + +#include "private/pvoidvector.h" #include "private/vector_base.h" #include @@ -59,14 +61,18 @@ SOFTWARE. namespace etl { + template + class ivector; + //*************************************************************************** /// The base class for specifically sized vectors. /// Can be used as a reference type for all vectors containing a specific /// type. + /// A vector for when T is not an object pointer. ///\ingroup vector //*************************************************************************** template - class ivector : public etl::vector_base + class ivector >::value>::type> : public etl::vector_base { public: @@ -85,10 +91,6 @@ namespace etl typedef size_t size_type; typedef typename etl::iterator_traits::difference_type difference_type; - protected: - - typedef typename etl::parameter_type::type parameter_t; - public: //********************************************************************* @@ -388,7 +390,10 @@ namespace etl ///\param last The iterator to the last element + 1. //********************************************************************* template - typename etl::enable_if::value, void>::type assign(TIterator first, TIterator last) + typename etl::enable_if::value + && etl::is_convertible::value_type, T>::value, + typename etl::enable_if::value, void>::type>::type + assign(TIterator first, TIterator last) ETL_NOEXCEPT_IF((etl::is_nothrow_copy_constructible::value && ETL_NOT_USING_EXCEPTIONS)) { #if ETL_USING_CPP11 ETL_STATIC_ASSERT((etl::is_same::type, @@ -414,7 +419,7 @@ namespace etl ///\param n The number of elements to add. ///\param value The value to insert for each element. //********************************************************************* - void assign(size_t n, parameter_t value) + void assign(size_t n, const_reference value) { ETL_ASSERT_OR_RETURN(n <= CAPACITY, ETL_ERROR(vector_full)); @@ -799,7 +804,7 @@ namespace etl ///\param n The number of elements to add. ///\param value The value to insert. //********************************************************************* - void insert(const_iterator position, size_t n, parameter_t value) + void insert(const_iterator position, size_t n, const_reference value) { ETL_ASSERT_OR_RETURN((size() + n) <= CAPACITY, ETL_ERROR(vector_full)); ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); @@ -857,7 +862,9 @@ namespace etl ///\param last The last + 1 element to add. //********************************************************************* template - void insert(const_iterator position, TIterator first, TIterator last, typename etl::enable_if::value, int>::type = 0) + typename etl::enable_if< + !etl::is_integral::value && etl::is_convertible::value_type, T>::value, void>::type + insert(const_iterator position, TIterator first, TIterator last, typename etl::enable_if::value, int>::type = 0) { size_t count = static_cast(etl::distance(first, last)); @@ -1174,6 +1181,557 @@ namespace etl } }; + //*************************************************************************** + /// The base class for specifically sized vectors. + /// Can be used as a reference type for all vectors containing a specific + /// type. + /// A vector for when T is an object pointer. + ///\ingroup vector + //*************************************************************************** + template + class ivector::value>::type> : public etl::pvoidvector + { + public: + + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; +#if ETL_USING_CPP11 + typedef T&& rvalue_reference; +#endif + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; + typedef ETL_OR_STD::reverse_iterator reverse_iterator; + typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; + typedef size_t size_type; + typedef typename etl::iterator_traits::difference_type difference_type; + + private: + + typedef pvoidvector base_t; + + typedef typename etl::remove_const::type>::type* element_type; + + template + struct is_compatible_iterator + : etl::bool_constant::value_type>::value + && etl::is_convertible::value_type, value_type>::value> + { + }; + + public: + + //********************************************************************* + /// Returns an iterator to the beginning of the vector. + ///\return An iterator to the beginning of the vector. + //********************************************************************* + iterator begin() + { + return iterator(base_t::begin()); + } + + //********************************************************************* + /// Returns a const_iterator to the beginning of the vector. + ///\return A const iterator to the beginning of the vector. + //********************************************************************* + const_iterator begin() const + { + return const_iterator(base_t::begin()); + } + + //********************************************************************* + /// Returns an iterator to the end of the vector. + ///\return An iterator to the end of the vector. + //********************************************************************* + iterator end() + { + return iterator(base_t::end()); + } + + //********************************************************************* + /// Returns a const_iterator to the end of the vector. + ///\return A const iterator to the end of the vector. + //********************************************************************* + const_iterator end() const + { + return const_iterator(base_t::end()); + } + + //********************************************************************* + /// Returns a const_iterator to the beginning of the vector. + ///\return A const iterator to the beginning of the vector. + //********************************************************************* + const_iterator cbegin() const + { + return const_iterator(base_t::cbegin()); + } + + //********************************************************************* + /// Returns a const_iterator to the end of the vector. + ///\return A const iterator to the end of the vector. + //********************************************************************* + const_iterator cend() const + { + return const_iterator(base_t::cend()); + } + + //********************************************************************* + /// Returns an reverse iterator to the reverse beginning of the vector. + ///\return Iterator to the reverse beginning of the vector. + //********************************************************************* + reverse_iterator rbegin() + { + return reverse_iterator(iterator(base_t::end())); + } + + //********************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the vector. + ///\return Const iterator to the reverse beginning of the vector. + //********************************************************************* + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(const_iterator(base_t::end())); + } + + //********************************************************************* + /// Returns a reverse iterator to the end + 1 of the vector. + ///\return Reverse iterator to the end + 1 of the vector. + //********************************************************************* + reverse_iterator rend() + { + return reverse_iterator(iterator(base_t::begin())); + } + + //********************************************************************* + /// Returns a const reverse iterator to the end + 1 of the vector. + ///\return Const reverse iterator to the end + 1 of the vector. + //********************************************************************* + const_reverse_iterator rend() const + { + return const_reverse_iterator(const_iterator(base_t::begin())); + } + + //********************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the vector. + ///\return Const reverse iterator to the reverse beginning of the vector. + //********************************************************************* + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(const_iterator(base_t::cend())); + } + + //********************************************************************* + /// Returns a const reverse iterator to the end + 1 of the vector. + ///\return Const reverse iterator to the end + 1 of the vector. + //********************************************************************* + const_reverse_iterator crend() const + { + return const_reverse_iterator(const_iterator(base_t::cbegin())); + } + + //********************************************************************* + /// Resizes the vector. + /// If asserts or exceptions are enabled and the new size is larger than the + /// maximum then a vector_full is thrown. + ///\param new_size The new size. + //********************************************************************* + void resize(size_t new_size) + { + base_t::resize(new_size); + } + + //********************************************************************* + /// Resizes the vector. + /// If asserts or exceptions are enabled and the new size is larger than the + /// maximum then a vector_full is thrown. + ///\param new_size The new size. + ///\param value The value to fill new elements with. Default = default + /// constructed value. + //********************************************************************* + void resize(size_t new_size, value_type value) + { + base_t::resize(new_size, to_void_ptr(value)); + } + + //********************************************************************* + /// Resizes the vector, but does not initialise new entries. + ///\param new_size The new size. + //********************************************************************* + void uninitialized_resize(size_t new_size) + { + base_t::uninitialized_resize(new_size); + } + + //********************************************************************* + /// Returns a reference to the value at index 'i' + ///\param i The index. + ///\return A reference to the value at index 'i' + //********************************************************************* + reference operator[](size_t i) + { + return reference(base_t::operator[](i)); + } + + //********************************************************************* + /// Returns a const reference to the value at index 'i' + ///\param i The index. + ///\return A const reference to the value at index 'i' + //********************************************************************* + const_reference operator[](size_t i) const + { + return const_reference(base_t::operator[](i)); + } + + //********************************************************************* + /// Returns a reference to the value at index 'i' + /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds + /// if the index is out of range. + ///\param i The index. + ///\return A reference to the value at index 'i' + //********************************************************************* + reference at(size_t i) + { + return reference(base_t::at(i)); + } + + //********************************************************************* + /// Returns a const reference to the value at index 'i' + /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds + /// if the index is out of range. + ///\param i The index. + ///\return A const reference to the value at index 'i' + //********************************************************************* + const_reference at(size_t i) const + { + return const_reference(base_t::at(i)); + } + + //********************************************************************* + /// Returns a reference to the first element. + ///\return A reference to the first element. + //********************************************************************* + reference front() + { + return reference(base_t::front()); + } + + //********************************************************************* + /// Returns a const reference to the first element. + ///\return A const reference to the first element. + //********************************************************************* + const_reference front() const + { + return const_reference(base_t::front()); + } + + //********************************************************************* + /// Returns a reference to the last element. + ///\return A reference to the last element. + //********************************************************************* + reference back() + { + return reference(base_t::back()); + } + + //********************************************************************* + /// Returns a const reference to the last element. + ///\return A const reference to the last element. + //********************************************************************* + const_reference back() const + { + return const_reference(base_t::back()); + } + + //********************************************************************* + /// Returns a pointer to the beginning of the vector data. + ///\return A pointer to the beginning of the vector data. + //********************************************************************* + pointer data() + { + return pointer(base_t::data()); + } + + //********************************************************************* + /// Returns a const pointer to the beginning of the vector data. + ///\return A const pointer to the beginning of the vector data. + //********************************************************************* + const_pointer data() const + { + return const_pointer(base_t::data()); + } + + //********************************************************************* + /// Assigns values to the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector + /// does not have enough free space. If asserts or exceptions are enabled, + /// emits vector_iterator if the iterators are reversed. + ///\param first The iterator to the first element. + ///\param last The iterator to the last element + 1. + //********************************************************************* + template + typename etl::enable_if::value, void>::type assign(TIterator first, TIterator last) + { + base_t::assign(first, last); + } + + //********************************************************************* + /// Assigns values to the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector + /// does not have enough free space. + ///\param n The number of elements to add. + ///\param value The value to insert for each element. + //********************************************************************* + void assign(size_t n, const_reference value) + { + base_t::assign(n, to_void_ptr(value)); + } + + //************************************************************************* + /// Clears the vector. + //************************************************************************* + void clear() + { + base_t::clear(); + } + + //********************************************************************* + /// Inserts a value at the end of the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector is + /// already full. + ///\param value The value to add. + //********************************************************************* + void push_back(const_reference value) + { + base_t::push_back(to_void_ptr(value)); + } + + //********************************************************************* + /// Constructs a value at the end of the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector is + /// already full. + ///\param value The value to add. + //********************************************************************* + reference emplace_back() + { + base_t::emplace_back(ETL_NULLPTR); + + return back(); + } + + //********************************************************************* + /// Constructs a value at the end of the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector is + /// already full. + ///\param value The value to add. + //********************************************************************* + reference emplace_back(const_reference value) + { + base_t::emplace_back(to_void_ptr(value)); + + return back(); + } + + //************************************************************************* + /// Removes an element from the end of the vector. + /// Does nothing if the vector is empty. + //************************************************************************* + void pop_back() + { + base_t::pop_back(); + } + + //********************************************************************* + /// Inserts a value to the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector is + /// already full. + ///\param position The position to insert before. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator position, const_reference value) + { + return iterator(base_t::insert(base_t::iterator(position), to_void_ptr(value))); + } + + //************************************************************************* + /// Emplaces a value to the vector at the specified position. + //************************************************************************* + iterator emplace(const_iterator position) + { + return iterator(base_t::emplace(base_t::iterator(position), ETL_NULLPTR)); + } + + //************************************************************************* + /// Emplaces a value to the vector at the specified position. + //************************************************************************* + iterator emplace(const_iterator position, const_reference value) + { + return iterator(base_t::emplace(base_t::iterator(position), to_void_ptr(value))); + } + + //********************************************************************* + /// Inserts 'n' values to the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector + /// does not have enough free space. + ///\param position The position to insert before. + ///\param n The number of elements to add. + ///\param value The value to insert. + //********************************************************************* + void insert(const_iterator position, size_t n, const_reference value) + { + base_t::insert(base_t::const_iterator(position), n, to_void_ptr(value)); + } + + //********************************************************************* + /// Inserts a range of values to the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector + /// does not have enough free space. + ///\param position The position to insert before. + ///\param first The first element to add. + ///\param last The last + 1 element to add. + //********************************************************************* + template + typename etl::enable_if< is_compatible_iterator::value, void>::type insert(const_iterator position, TIterator first, TIterator last) + { + base_t::insert(base_t::const_iterator(position), first, last); + } + + //********************************************************************* + /// Erases an element. + ///\param i_element Iterator to the element. + ///\return An iterator pointing to the element that followed the erased + /// element. + //********************************************************************* + iterator erase(iterator i_element) + { + return iterator(base_t::erase(base_t::iterator(i_element))); + } + + //********************************************************************* + /// Erases an element. + ///\param i_element Iterator to the element. + ///\return An iterator pointing to the element that followed the erased + /// element. + //********************************************************************* + iterator erase(const_iterator i_element) + { + return iterator(base_t::erase(base_t::const_iterator(i_element))); + } + + //********************************************************************* + /// Erases a range of elements. + /// The range includes all the elements between first and last, including + /// the element pointed by first, but not the one pointed by last. + ///\param first Iterator to the first element. + ///\param last Iterator to the last element. + ///\return An iterator pointing to the element that followed the erased + /// element. + //********************************************************************* + iterator erase(const_iterator first, const_iterator last) + { + return iterator(base_t::erase(base_t::const_iterator(first), base_t::const_iterator(last))); + } + + //********************************************************************* + /// Swap contents with another vector. Performs operation on each + /// individual element. + ///\param other The other vector to swap with. + //********************************************************************* + void swap(ivector& other) + { + if (this == &other) + { + return; + } + + ETL_ASSERT_OR_RETURN(this->max_size() >= other.size() && other.max_size() >= this->size(), ETL_ERROR(vector_full)); + + ivector& smaller = other.size() > this->size() ? *this : other; + ivector& larger = other.size() > this->size() ? other : *this; + + etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + + typename ivector::iterator larger_itr = etl::next(larger.begin(), static_cast(smaller.size())); + + etl::move(larger_itr, larger.end(), etl::back_inserter(smaller)); + + larger.erase(larger_itr, larger.end()); + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + ivector& operator=(const ivector& rhs) + { + base_t::operator=(rhs); + + return *this; + } + +#if ETL_USING_CPP11 + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + ivector& operator=(ivector&& rhs) + { + (void)base_t::operator=(etl::move(rhs)); + + return *this; + } +#endif + +#ifdef ETL_IVECTOR_REPAIR_ENABLE + //************************************************************************* + /// Fix the internal pointers after a low level memory copy. + //************************************************************************* + virtual void repair() = 0; +#endif + + protected: + + //********************************************************************* + /// Constructor. + //********************************************************************* + ivector(pointer p_buffer_, size_t MAX_SIZE) ETL_NOEXCEPT + : pvoidvector(to_void_pptr(p_buffer_), MAX_SIZE) + { + } + + //********************************************************************* + /// Initialise the vector. + //********************************************************************* + void initialise() + { + base_t::initialise(); + } + + //************************************************************************* + /// Fix the internal pointers after a low level memory copy. + //************************************************************************* + void repair_buffer(pointer p_buffer_) + { + base_t::repair_buffer(to_void_pptr(p_buffer_)); + } + + private: + + // Disable copy construction. + ivector(const ivector&) ETL_DELETE; + + // Convert from const_reference to void* + static ETL_CONSTEXPR14 void* to_void_ptr(const_reference value) ETL_NOEXCEPT + { + return const_cast(static_cast(value)); + } + + // Convert from pointer to void** + static ETL_CONSTEXPR14 void** to_void_pptr(pointer p_buffer) ETL_NOEXCEPT + { + return reinterpret_cast(const_cast(p_buffer)); + } + }; + //*************************************************************************** /// Equal operator. ///\param lhs Reference to the first vector. @@ -1255,10 +1813,12 @@ namespace etl } } // namespace etl -#include "private/ivectorpointer.h" - namespace etl { + //*************************************************************************** + template + class vector; + //*************************************************************************** /// A vector implementation that uses a fixed size buffer. ///\tparam T The element type. @@ -1299,7 +1859,7 @@ namespace etl ///\param initial_size The initial size of the vector. ///\param value The value to fill the vector with. //************************************************************************* - vector(size_t initial_size, typename etl::ivector::parameter_t value) + vector(size_t initial_size, typename etl::ivector::const_reference value) : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { this->initialise(); @@ -1481,7 +2041,7 @@ namespace etl ///\param initial_size The initial size of the vector_ext. ///\param value The value to fill the vector_ext with. //************************************************************************* - vector_ext(size_t initial_size, typename etl::ivector::parameter_t value, void* buffer, size_t max_size) + vector_ext(size_t initial_size, typename etl::ivector::const_reference value, void* buffer, size_t max_size) : etl::ivector(reinterpret_cast(buffer), max_size) { this->initialise(); @@ -1517,15 +2077,19 @@ namespace etl /// Copy constructor. //************************************************************************* vector_ext(const vector_ext& other, void* buffer, size_t max_size) + ETL_NOEXCEPT_IF((etl::is_nothrow_copy_constructible::value && ETL_NOT_USING_EXCEPTIONS)) : etl::ivector(reinterpret_cast(buffer), max_size) { - this->assign(other.begin(), other.end()); + if (&other != this) + { + this->assign(other.begin(), other.end()); + } } //************************************************************************* /// Assignment operator. //************************************************************************* - vector_ext& operator=(const vector_ext& rhs) + vector_ext& operator=(const vector_ext& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_copy_constructible::value && ETL_NOT_USING_EXCEPTIONS)) { if (&rhs != this) { @@ -1539,19 +2103,13 @@ namespace etl //************************************************************************* /// Move constructor. //************************************************************************* - vector_ext(vector_ext&& other, void* buffer, size_t max_size) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) + vector_ext(vector_ext&& other, void* buffer, size_t max_size) + ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value && ETL_NOT_USING_EXCEPTIONS)) : etl::ivector(reinterpret_cast(buffer), max_size) { - if (this != &other) + if (&other != this) { - this->initialise(); - - typename etl::ivector::iterator itr = other.begin(); - while (itr != other.end()) - { - this->push_back(etl::move(*itr)); - ++itr; - } + this->assign(etl::make_move_iterator(other.begin()), etl::make_move_iterator(other.end())); other.initialise(); } @@ -1560,18 +2118,11 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - vector_ext& operator=(vector_ext&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) + vector_ext& operator=(vector_ext&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value && ETL_NOT_USING_EXCEPTIONS)) { if (&rhs != this) { - this->clear(); - - typename etl::ivector::iterator itr = rhs.begin(); - while (itr != rhs.end()) - { - this->push_back(etl::move(*itr)); - ++itr; - } + this->assign(etl::make_move_iterator(rhs.begin()), etl::make_move_iterator(rhs.end())); rhs.initialise(); } @@ -1600,289 +2151,6 @@ namespace etl } }; - //*************************************************************************** - /// A vector implementation that uses a fixed size buffer. - ///\tparam T The element type. - ///\tparam MAX_SIZE_ The maximum number of elements that can be stored. - ///\ingroup vector - //*************************************************************************** - template - class vector : public etl::ivector - { - public: - - ETL_STATIC_ASSERT((MAX_SIZE_ > 0U), "Zero capacity etl::vector is not valid"); - - static const size_t MAX_SIZE = MAX_SIZE_; - - //************************************************************************* - /// Constructor. - //************************************************************************* - vector() ETL_NOEXCEPT - : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) - { - this->initialise(); - } - - //************************************************************************* - /// Constructor, with size. - ///\param initial_size The initial size of the vector. - //************************************************************************* - explicit vector(size_t initial_size) - : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) - { - this->initialise(); - this->resize(initial_size); - } - - //************************************************************************* - /// Constructor, from initial size and value. - ///\param initial_size The initial size of the vector. - ///\param value The value to fill the vector with. - //************************************************************************* - vector(size_t initial_size, typename etl::ivector::parameter_t value) - : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) - { - this->initialise(); - this->resize(initial_size, value); - } - - //************************************************************************* - /// Constructor, from an iterator range. - ///\tparam TIterator The iterator type. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //************************************************************************* - template - vector(TIterator first, TIterator last, typename etl::enable_if::value, int>::type = 0) - : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) - { - this->assign(first, last); - } - -#if ETL_HAS_INITIALIZER_LIST - //************************************************************************* - /// Constructor, from an initializer_list. - //************************************************************************* - vector(std::initializer_list init) - : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) - { - this->assign(init.begin(), init.end()); - } -#endif - - //************************************************************************* - /// Copy constructor. - //************************************************************************* - vector(const vector& other) - : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) - { - (void)etl::ivector::operator=(other); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - vector& operator=(const vector& rhs) - { - (void)etl::ivector::operator=(rhs); - - return *this; - } - -#if ETL_USING_CPP11 - //************************************************************************* - /// Move constructor. - //************************************************************************* - vector(vector&& other) ETL_NOEXCEPT - : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) - { - (void)etl::ivector::operator=(etl::move(other)); - } - - //************************************************************************* - /// Move assignment operator. - //************************************************************************* - vector& operator=(vector&& rhs) ETL_NOEXCEPT - { - (void)etl::ivector::operator=(etl::move(rhs)); - - return *this; - } -#endif - - //************************************************************************* - /// Fix the internal pointers after a low level memory copy. - //************************************************************************* -#ifdef ETL_IVECTOR_REPAIR_ENABLE - virtual void repair() ETL_OVERRIDE -#else - void repair() -#endif - { - etl::ivector::repair_buffer(buffer); - } - - private: - - typename etl::aligned_storage::value>::type buffer; - }; - - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST - template - vector(T*...) -> vector, sizeof...(T)>; -#endif - -#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST - template - constexpr auto make_vector(T*... t) -> etl::vector, sizeof...(T)> - { - return {etl::forward(t)...}; - } -#endif - - //*************************************************************************** - /// A vector implementation that uses a fixed size buffer. - /// The buffer is supplied on construction. - ///\tparam T The element type that is pointed to. - ///\ingroup vector - //*************************************************************************** - template - class vector_ext : public etl::ivector - { - public: - - //************************************************************************* - /// Constructor. - //************************************************************************* - vector_ext(void* buffer, size_t max_size) ETL_NOEXCEPT - : etl::ivector(reinterpret_cast(buffer), max_size) - { - this->initialise(); - } - - //************************************************************************* - /// Constructor, with size. - ///\param initial_size The initial size of the vector_ext. - //************************************************************************* - vector_ext(size_t initial_size, void* buffer, size_t max_size) - : etl::ivector(reinterpret_cast(buffer), max_size) - { - this->initialise(); - this->resize(initial_size); - } - - //************************************************************************* - /// Constructor, from initial size and value. - ///\param initial_size The initial size of the vector_ext. - ///\param value The value to fill the vector_ext with. - //************************************************************************* - vector_ext(size_t initial_size, typename etl::ivector::parameter_t value, void* buffer, size_t max_size) - : etl::ivector(reinterpret_cast(buffer), max_size) - { - this->initialise(); - this->resize(initial_size, value); - } - - //************************************************************************* - /// Constructor, from an iterator range. - ///\tparam TIterator The iterator type. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //************************************************************************* - template - vector_ext(TIterator first, TIterator last, void* buffer, size_t max_size, - typename etl::enable_if::value, int>::type = 0) - : etl::ivector(reinterpret_cast(buffer), max_size) - { - this->assign(first, last); - } - -#if ETL_HAS_INITIALIZER_LIST - //************************************************************************* - /// Constructor, from an initializer_list. - //************************************************************************* - vector_ext(std::initializer_list init, void* buffer, size_t max_size) - : etl::ivector(reinterpret_cast(buffer), max_size) - { - this->assign(init.begin(), init.end()); - } -#endif - - //************************************************************************* - /// Construct a copy. - //************************************************************************* - vector_ext(const vector_ext& other, void* buffer, size_t max_size) - : etl::ivector(reinterpret_cast(buffer), max_size) - { - (void)etl::ivector::operator=(other); - } - - //************************************************************************* - /// Copy constructor (Deleted) - //************************************************************************* - vector_ext(const vector_ext& other) ETL_DELETE; - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - vector_ext& operator=(const vector_ext& rhs) - { - (void)etl::ivector::operator=(rhs); - - return *this; - } - -#if ETL_USING_CPP11 - //************************************************************************* - /// Move constructor. - //************************************************************************* - vector_ext(vector_ext&& other, void* buffer, size_t max_size) - : etl::ivector(reinterpret_cast(buffer), max_size) - { - (void)etl::ivector::operator=(etl::move(other)); - } - - //************************************************************************* - /// Move constructor (Deleted) - //************************************************************************* - vector_ext(vector_ext&& other) ETL_DELETE; - - //************************************************************************* - /// Move assignment operator. - //************************************************************************* - vector_ext& operator=(vector_ext&& rhs) - { - (void)etl::ivector::operator=(etl::move(rhs)); - - return *this; - } -#endif - - //************************************************************************* - /// Destructor. - //************************************************************************* - ~vector_ext() ETL_NOEXCEPT - { - this->clear(); - } - - //************************************************************************* - /// Fix the internal pointers after a low level memory copy. - //************************************************************************* -#ifdef ETL_IVECTOR_REPAIR_ENABLE - virtual void repair() ETL_OVERRIDE -#else - void repair() -#endif - { - etl::ivector::repair_buffer(this->p_buffer); - } - }; - //*************************************************************************** /// erase //*************************************************************************** diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 042d428d..b545384d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -374,6 +374,10 @@ add_executable(etl_tests test_vector_non_trivial.cpp test_vector_pointer.cpp test_vector_pointer_external_buffer.cpp + test_vector_function_pointer.cpp + test_vector_function_pointer_external_buffer.cpp + test_vector_member_function_pointer.cpp + test_vector_member_function_pointer_external_buffer.cpp test_visitor.cpp test_xor_checksum.cpp test_xor_rotate_checksum.cpp diff --git a/test/meson.build b/test/meson.build index 14fd63ad..1ab6bd6a 100644 --- a/test/meson.build +++ b/test/meson.build @@ -362,6 +362,10 @@ etl_test_sources = files( 'test_vector_non_trivial.cpp', 'test_vector_pointer.cpp', 'test_vector_pointer_external_buffer.cpp', + 'test_vector_function_pointer.cpp', + 'test_vector_function_pointer_external_buffer.cpp', + 'test_vector_member_function_pointer.cpp', + 'test_vector_member_function_pointer_external_buffer.cpp', 'test_visitor.cpp', 'test_xor_checksum.cpp', 'test_xor_rotate_checksum.cpp' diff --git a/test/test_circular_iterator.cpp b/test/test_circular_iterator.cpp index da0f6c95..09a9f3e9 100644 --- a/test/test_circular_iterator.cpp +++ b/test/test_circular_iterator.cpp @@ -593,6 +593,7 @@ namespace //************************************************************************* TEST(test_conversion_operator_for_forward_iterator) { +#include "etl/private/diagnostic_null_dereference_push.h" DataF data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; etl::circular_iterator ci(std::begin(data), std::end(data)); @@ -607,6 +608,7 @@ namespace ++itr; ++ci; CHECK(itr == ci.current()); +#include "etl/private/diagnostic_pop.h" } //************************************************************************* diff --git a/test/test_deque.cpp b/test/test_deque.cpp index 9daf01b8..a09f67d5 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -2306,7 +2306,9 @@ namespace data.fill(N999); +#include "etl/private/diagnostic_uninitialized_push.h" CHECK(std::equal(blank_data.begin(), blank_data.end(), data.begin())); +#include "etl/private/diagnostic_pop.h" } //************************************************************************* @@ -2319,6 +2321,7 @@ namespace // Access via const_iterator operator[] DataNDC::const_iterator cit = cdata.begin(); +#include "etl/private/diagnostic_uninitialized_push.h" // Verify operator[] returns values matching sequential access for (size_t i = 0; i < cdata.size(); ++i) { @@ -2330,6 +2333,7 @@ namespace // the type would be non-const reference which is incorrect for const_iterator) const NDC& ref = cit[0]; CHECK(ref == cdata[0]); +#include "etl/private/diagnostic_pop.h" } } } // namespace diff --git a/test/test_map.cpp b/test/test_map.cpp index 9d8d6176..c57b5b5e 100644 --- a/test/test_map.cpp +++ b/test/test_map.cpp @@ -1720,6 +1720,7 @@ namespace { using Pair = std::pair; + #include "etl/private/diagnostic_null_dereference_push.h" etl::map data{Pair{"0", 0}, Pair{"1", 1}, Pair{"2", 2}, Pair{"3", 3}, Pair{"4", 4}, Pair{"5", 5}}; auto v = *data.begin(); @@ -1732,6 +1733,7 @@ namespace CHECK_EQUAL(3, data.at("3")); CHECK_EQUAL(4, data.at("4")); CHECK_EQUAL(5, data.at("5")); + #include "etl/private/diagnostic_pop.h" CHECK_TRUE(std::is_sorted(data.begin(), data.end(), data.value_comp())); } @@ -1743,6 +1745,7 @@ namespace { using Pair = ETL_OR_STD::pair; + #include "etl/private/diagnostic_null_dereference_push.h" auto data = etl::make_map>(Pair{"0", 0}, Pair{"1", 1}, Pair{"2", 2}, Pair{"3", 3}, Pair{"4", 4}, Pair{"5", 5}); @@ -1756,6 +1759,7 @@ namespace CHECK_EQUAL(3, data.at("3")); CHECK_EQUAL(4, data.at("4")); CHECK_EQUAL(5, data.at("5")); + #include "etl/private/diagnostic_pop.h" CHECK_TRUE(std::is_sorted(data.begin(), data.end(), data.value_comp())); } diff --git a/test/test_variant_variadic.cpp b/test/test_variant_variadic.cpp index b9f7a04b..080b0550 100644 --- a/test/test_variant_variadic.cpp +++ b/test/test_variant_variadic.cpp @@ -1167,6 +1167,7 @@ namespace } //************************************************************************* + #include "etl/private/diagnostic_uninitialized_push.h" TEST(test_const_variant_accept_visitor) { struct Visitor : public etl::visitor @@ -1217,8 +1218,10 @@ namespace const_variant_etl3.accept(visitor); CHECK_EQUAL("3", visitor.result_s); } + #include "etl/private/diagnostic_pop.h" //************************************************************************* + #include "etl/private/diagnostic_uninitialized_push.h" TEST(test_const_variant_accept_visitor_deprecated) { struct Visitor : public etl::visitor @@ -1271,6 +1274,7 @@ namespace const_variant_etl3.accept(visitor); CHECK_EQUAL("3", visitor.result_s); } + #include "etl/private/diagnostic_pop.h" //************************************************************************* TEST(test_variant_accept_functor_with_functor_class) @@ -1378,6 +1382,7 @@ namespace } //************************************************************************* + #include "etl/private/diagnostic_uninitialized_push.h" TEST(test_const_variant_accept_functor_with_functor_class) { struct Visitor @@ -1428,8 +1433,10 @@ namespace const_variant_etl3.accept(visitor); CHECK_EQUAL("3", visitor.result_s); } + #include "etl/private/diagnostic_pop.h" //************************************************************************* + #include "etl/private/diagnostic_uninitialized_push.h" TEST(test_const_variant_accept_functor_with_functor_class_deprecated) { struct Visitor @@ -1480,6 +1487,7 @@ namespace const_variant_etl3.accept(visitor); CHECK_EQUAL("3", visitor.result_s); } + #include "etl/private/diagnostic_pop.h" //************************************************************************* #if ETL_USING_CPP17 @@ -1549,7 +1557,8 @@ namespace CHECK_EQUAL("3", result_s); } - //************************************************************************* + //************************************************************************* + #include "etl/private/diagnostic_uninitialized_push.h" TEST(test_const_variant_accept_functor_with_overload) { char result_c; @@ -1576,8 +1585,10 @@ namespace const_variant_etl3.accept(visitor); CHECK_EQUAL("3", result_s); } + #include "etl/private/diagnostic_pop.h" - //************************************************************************* + //************************************************************************* + #include "etl/private/diagnostic_uninitialized_push.h" TEST(test_const_variant_accept_functor_with_overload_deprecated) { char result_c; @@ -1604,6 +1615,7 @@ namespace const_variant_etl3.accept(visitor); CHECK_EQUAL("3", result_s); } + #include "etl/private/diagnostic_pop.h" #endif //************************************************************************* diff --git a/test/test_vector.cpp b/test/test_vector.cpp index 49f84e80..b9957e5d 100644 --- a/test/test_vector.cpp +++ b/test/test_vector.cpp @@ -1077,13 +1077,15 @@ namespace Compare_Data compare_data(initial_data.begin(), initial_data.end()); Data data(initial_data.begin(), initial_data.end()); - Compare_Data::iterator const_cdi = compare_data.begin() + 2U; - int compare_value = *(const_cdi + 1U); - Compare_Data::iterator cdi = compare_data.erase(const_cdi); + Compare_Data::iterator const_cdi = compare_data.begin() + 2U; +#include "etl/private/diagnostic_null_dereference_push.h" + int compare_value = compare_data[3]; +#include "etl/private/diagnostic_pop.h" + Compare_Data::iterator cdi = compare_data.erase(const_cdi); CHECK_EQUAL(compare_value, *cdi); Data::iterator const_di = data.begin() + 2U; - int data_value = *(const_di + 1U); + int data_value = data[3]; Data::iterator di = data.erase(const_di); CHECK_EQUAL(data_value, *di); @@ -1108,13 +1110,15 @@ namespace Compare_Data compare_data(initial_data.begin(), initial_data.end()); Data data(initial_data.begin(), initial_data.end()); - Compare_Data::const_iterator const_cdi = compare_data.cbegin() + 2U; - int compare_value = *(const_cdi + 1U); - Compare_Data::iterator cdi = compare_data.erase(const_cdi); + Compare_Data::const_iterator const_cdi = compare_data.cbegin() + 2U; +#include "etl/private/diagnostic_null_dereference_push.h" + int compare_value = compare_data[3]; +#include "etl/private/diagnostic_pop.h" + Compare_Data::iterator cdi = compare_data.erase(const_cdi); CHECK_EQUAL(compare_value, *cdi); Data::const_iterator const_di = data.cbegin() + 2U; - int data_value = *(const_di + 1U); + int data_value = data[3]; Data::iterator di = data.erase(const_di); CHECK_EQUAL(data_value, *di); @@ -1139,15 +1143,9 @@ namespace Compare_Data compare_data(initial_data.begin(), initial_data.end()); Data data(initial_data.begin(), initial_data.end()); - Compare_Data::const_iterator const_cdi = compare_data.cbegin() + 2U; - int compare_value = *(const_cdi + 2U); - Compare_Data::iterator cdi = compare_data.erase(const_cdi, const_cdi + 2U); - CHECK_EQUAL(compare_value, *cdi); + compare_data.erase(compare_data.begin() + 2, compare_data.begin() + 4); - Data::const_iterator const_di = data.cbegin() + 2U; - int data_value = *(const_di + 2U); - Data::iterator di = data.erase(const_di, const_di + 2U); - CHECK_EQUAL(data_value, *di); + data.erase(data.begin() + 2, data.begin() + 4); CHECK_EQUAL(compare_data.size(), data.size()); diff --git a/test/test_vector_external_buffer.cpp b/test/test_vector_external_buffer.cpp index 814946f3..33a6651a 100644 --- a/test/test_vector_external_buffer.cpp +++ b/test/test_vector_external_buffer.cpp @@ -46,6 +46,8 @@ namespace int buffer4[SIZE]; int buffer5[SIZE]; + int bufferLarger[SIZE + 1]; + SUITE(test_vector_external_buffer) { typedef etl::vector_ext Data; @@ -183,6 +185,14 @@ namespace CHECK(data2 != data); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_construct_from_larger_vector_ext) + { + Data data(initial_data.begin(), initial_data.end(), bufferLarger, SIZE + 1); + data.resize(SIZE + 1, 0); + CHECK_THROW(Data data2(data, buffer1, SIZE), etl::vector_full); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_move_constructor) { @@ -193,6 +203,14 @@ namespace CHECK(data2 != data); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_construct_from_larger_vector_ext) + { + Data data(initial_data.begin(), initial_data.end(), bufferLarger, SIZE + 1); + data.resize(SIZE + 1, 0); + CHECK_THROW(Data data2(etl::move(data), buffer1, SIZE), etl::vector_full); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_vector_function_pointer.cpp b/test/test_vector_function_pointer.cpp new file mode 100644 index 00000000..62b18a71 --- /dev/null +++ b/test/test_vector_function_pointer.cpp @@ -0,0 +1,1321 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 John Wellbelove + +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 "unit_test_framework.h" + +#include +#include +#include +#include + +#include "etl/vector.h" + +namespace +{ + size_t f0(size_t a) + { + return 0 * a; + } + size_t f1(size_t a) + { + return 1 * a; + } + size_t f2(size_t a) + { + return 2 * a; + } + size_t f3(size_t a) + { + return 3 * a; + } + size_t f4(size_t a) + { + return 4 * a; + } + size_t f5(size_t a) + { + return 5 * a; + } + size_t f6(size_t a) + { + return 6 * a; + } + size_t f7(size_t a) + { + return 7 * a; + } + size_t f8(size_t a) + { + return 8 * a; + } + size_t f9(size_t a) + { + return 9 * a; + } + size_t f10(size_t a) + { + return 10 * a; + } + size_t f11(size_t a) + { + return 11 * a; + } + size_t f12(size_t a) + { + return 12 * a; + } + + SUITE(test_vector_function_pointer) + { + static const size_t SIZE = 10; + + using FPtr = size_t (*)(size_t); + + using Data = etl::vector; + using IData = etl::ivector; + using Compare_Data = std::vector; + + Compare_Data initial_data; + Compare_Data less_data; + Compare_Data greater_data; + Compare_Data shorter_data; + Compare_Data different_data; + Compare_Data insert_data; + Compare_Data swap_data; + Compare_Data swap_other_data; + + //************************************************************************* + struct SetupFixture + { + SetupFixture() + { + FPtr n[] = {&f0, &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9}; + FPtr n_insert[] = {&f10, &f11, &f12}; + FPtr n_less[] = {&f0, &f1, &f2, &f3, &f3, &f5, &f6, &f7, &f8, &f9}; + FPtr n_greater[] = {&f0, &f1, &f2, &f4, &f4, &f5, &f6, &f7, &f8, &f9}; + FPtr n_swap[] = {&f0, &f1, &f2, &f3, &f4, &f5}; + FPtr n_swap_other[] = {&f6, &f7, &f8, &f9}; + + initial_data.assign(std::begin(n), std::end(n)); + insert_data.assign(std::begin(n_insert), std::end(n_insert)); + less_data.assign(std::begin(n_less), std::end(n_less)); + greater_data.assign(std::begin(n_greater), std::end(n_greater)); + shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); + different_data.assign(initial_data.rbegin(), initial_data.rend()); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); + } + }; + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_default_constructor) + { + Data data; + + CHECK_EQUAL(data.size(), size_t(0)); + CHECK(data.empty()); + CHECK_EQUAL(data.capacity(), SIZE); + CHECK_EQUAL(data.max_size(), SIZE); + } + +#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED) + //************************************************************************* + TEST(test_cpp17_deduced_constructor) + { + etl::vector data{&f0, &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9}; + etl::vector check = {&f0, &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9}; + + CHECK(!data.empty()); + CHECK(data.full()); + CHECK(data.begin() != data.end()); + CHECK_EQUAL(0U, data.available()); + CHECK_EQUAL(10U, data.capacity()); + CHECK_EQUAL(10U, data.size()); + CHECK_EQUAL(10U, data.max_size()); + CHECK(data == check); + } +#endif + + //************************************************************************* + TEST(test_iterator_comparison_empty) + { + Data data; + + CHECK(data.begin() == data.end()); + CHECK(data.cbegin() == data.cend()); + CHECK(data.rbegin() == data.rend()); + CHECK(data.crbegin() == data.crend()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size) + { + const size_t Initial_Size = 5; + Data data(Initial_Size); + + CHECK(data.size() == Initial_Size); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_value) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data(Initial_Size, Initial_Value); + + CHECK(data.size() == Initial_Size); + CHECK(!data.empty()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_excess) + { + CHECK_THROW(Data data(SIZE + 1), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + CHECK(data.size() == SIZE); + CHECK(!data.empty()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + +#if ETL_HAS_INITIALIZER_LIST + //************************************************************************* + TEST(test_constructor_initializer_list) + { + FPtr a = &f0; + FPtr b = &f1; + FPtr c = &f2; + FPtr d = &f3; + + Compare_Data compare_data = {a, b, c, d}; + Data data = {a, b, c, d}; + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + Data data(initial_data.begin(), initial_data.end()); + Data data2(data); + CHECK(data2 == data); + + data2[2] = nullptr; + CHECK(data2 != data); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_constructor) + { + Data data(initial_data.begin(), initial_data.end()); + Data data2(std::move(data)); + + CHECK_EQUAL(0U, data.size()); + CHECK_EQUAL(initial_data.size(), data2.size()); + + CHECK_EQUAL(initial_data.size(), data2.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment) + { + Data data(initial_data.begin(), initial_data.end()); + Data other_data; + + other_data = data; + + CHECK_EQUAL(initial_data.size(), data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_from_pointer_range) + { + Data data(initial_data.data(), initial_data.data() + initial_data.size()); + Data other_data; + + other_data = data; + + CHECK_EQUAL(initial_data.size(), data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + Data data(initial_data.begin(), initial_data.end()); + Data other_data; + other_data.push_back(Data::value_type(0)); + + other_data = std::move(data); + + CHECK_EQUAL(0U, data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_iterface) + { + Data data1(initial_data.begin(), initial_data.end()); + Data data2; + + IData& idata1 = data1; + IData& idata2 = data2; + + idata2 = idata1; + + bool is_equal = std::equal(data1.begin(), data1.end(), data2.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_self_assignment) + { + Data data(initial_data.begin(), initial_data.end()); + Data other_data(data); + +#include "etl/private/diagnostic_self_assign_overloaded_push.h" + other_data = other_data; +#include "etl/private/diagnostic_pop.h" + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_begin) + { + Data data(10); + const Data constData(10); + + CHECK_TRUE(&data[0] == data.begin()); + CHECK_TRUE(&constData[0] == constData.begin()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_end) + { + Data data(10); + const Data constData(10); + + CHECK_EQUAL(data.begin() + data.size(), data.end()); + CHECK_EQUAL(constData.begin() + constData.size(), constData.end()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 8; + + Data data(Initial_Size); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up_value) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 8; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, Initial_Value); + data.resize(NEW_SIZE, Initial_Value); + + std::array compare_data; + compare_data.fill(Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_excess) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = SIZE + 1; + + Data data(Initial_Size); + + CHECK_THROW(data.resize(NEW_SIZE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 2; + + Data data(Initial_Size); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down_value) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 2; + FPtr Initial_Value = &f0; + + Data data(Initial_Size); + data.resize(NEW_SIZE, Initial_Value); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_empty) + { + Data data; + data.resize(data.max_size()); + + CHECK(data.full()); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_full) + { + Data data; + + CHECK(!data.full()); + CHECK(data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data[i] == compare_data[i]); + } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end()); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data[i] == compare_data[i]); + } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data.at(i) == compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end()); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data.at(i) == compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + +#include "etl/private/diagnostic_uninitialized_push.h" + CHECK(data.front() == compare_data.front()); +#include "etl/private/diagnostic_pop.h" + + Data emptyData; + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end()); + +#include "etl/private/diagnostic_uninitialized_push.h" + CHECK(data.front() == compare_data.front()); +#include "etl/private/diagnostic_pop.h" + + const Data emptyData; + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + CHECK(data.back() == compare_data.back()); + + Data emptyData; + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end()); + + CHECK(data.back() == compare_data.back()); + + const Data emptyData; + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.data(), data.data() + data.size(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data_const) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.data(), data.data() + data.size(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data; + + data.assign(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_size_value) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data; + data.assign(Initial_Size, Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_size_value_excess) + { + const size_t Initial_Size = SIZE; + const size_t EXCESS_SIZE = SIZE + 1; + FPtr Initial_Value = &f0; + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data; + + CHECK_THROW(data.assign(EXCESS_SIZE, Initial_Value), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back) + { + Compare_Data compare_data; + Data data; + + FPtr fptr = &f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + compare_data.push_back(fptr); + } + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.push_back(fptr); + } + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back_excess) + { + Data data; + + FPtr fptr = &f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.push_back(fptr); + } + + CHECK_THROW(data.push_back(fptr), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back) + { + Compare_Data compare_data; + Data data; + + FPtr fptr = &f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + compare_data.emplace_back(fptr); + } + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.emplace_back(fptr); + } + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back_return) + { + Data data; + FPtr fptr1 = &f0; + FPtr fptr2 = &f1; + + data.emplace_back(fptr1); + CHECK_TRUE(fptr2 == data.emplace_back(fptr2)); + } + + //************************************************************************* + TEST(test_emplace_default) + { + static FPtr initial = &f0; + + // First fill with Initial values. + etl::vector data; + data.resize(SIZE, initial); + data.clear(); + + // Then emplace Default values. + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace(data.begin()); + } + + // Compare with an array of default values. + std::array compare_data; + compare_data.fill(nullptr); + + CHECK_TRUE(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(test_emplace_back_default) + { + static FPtr initial = &f0; + + // First fill with initial values. + etl::vector data; + data.resize(SIZE, initial); + data.clear(); + + // Then emplace default values. + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace_back(); + } + + // Compare with an array of default values. + std::array compare_data; + compare_data.fill(nullptr); + + CHECK_TRUE(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + compare_data.pop_back(); + compare_data.pop_back(); + + data.pop_back(); + data.pop_back(); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back_exception) + { + Data data; + + data.resize(2); + + data.pop_back(); + data.pop_back(); + + CHECK_THROW(data.pop_back(), etl::vector_empty); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + + data.insert(data.begin() + offset, Initial_Value); + compare_data.insert(compare_data.begin() + static_cast(offset), Initial_Value); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + Data data; + Data data2; + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + CHECK_THROW(data.insert(data2.cbegin(), Initial_Value), etl::vector_out_of_bounds); + } + + //************************************************************************* +#include "etl/private/diagnostic_array_bounds_push.h" + TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) + { + const size_t Initial_Size = SIZE; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, Initial_Value); + + size_t offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + + offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + } +#include "etl/private/diagnostic_pop.h" + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + + data.emplace(data.begin() + offset, Initial_Value); + compare_data.emplace(compare_data.begin() + static_cast(offset), Initial_Value); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value_outofbounds) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + Data data; + Data data2; + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + CHECK_THROW(data.emplace(data2.cbegin(), Initial_Value), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value) + { + const size_t Initial_Size = 5; + const size_t INSERT_SIZE = 3; + FPtr Initial_Value = &f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value); + compare_data.insert(compare_data.begin() + static_cast(offset), INSERT_SIZE, Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + FPtr Initial_Value = &f0; + Data data; + Data data2; + +#include "etl/private/diagnostic_uninitialized_push.h" + CHECK_THROW(data.insert(data2.end(), 1, Initial_Value);, etl::vector_out_of_bounds); +#include "etl/private/diagnostic_pop.h" + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) + { + const size_t Initial_Size = SIZE; + const size_t INSERT_SIZE = 4; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, Initial_Value); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range) + { + const size_t Initial_Size = 5; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.begin() + offset, insert_data.begin(), insert_data.end()); + compare_data.insert(compare_data.begin() + static_cast(offset), insert_data.begin(), insert_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_out_of_bounds) + { + Data data; + Data data2; + + CHECK_THROW(data.insert(data2.end(), insert_data.cbegin(), insert_data.cend());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_pointer_range) + { + const size_t Initial_Size = 5; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.data(), initial_data.data() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.data() + offset, insert_data.data(), insert_data.data() + insert_data.size()); + compare_data.insert(compare_data.begin() + static_cast(offset), insert_data.begin(), insert_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_pointer_range_out_of_bounds) + { + Data data; + + CHECK_THROW(data.insert(data.data() + data.size() + 1, insert_data.data(), insert_data.data() + insert_data.size()); + , etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, Initial_Value); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + Compare_Data::iterator citr = compare_data.erase(compare_data.begin() + 2); + Data::iterator ditr = data.erase(data.begin() + 2); + + CHECK(*citr == *ditr); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Data data(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.erase(data.end());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + Compare_Data::iterator citr = compare_data.erase(compare_data.cbegin() + 2, compare_data.cbegin() + 4); + Data::iterator ditr = data.erase(data.cbegin() + 2, data.cbegin() + 4); + + CHECK(*citr == *ditr); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Data data(initial_data.begin(), initial_data.end()); + Data data2(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.erase(data2.begin(), data2.end());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + data.clear(); + + CHECK_EQUAL(data.size(), size_t(0)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.cbegin(), data.cend(), compare_data.cbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_reverse_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.rbegin(), data.rend(), compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.crbegin(), data.crend(), compare_data.crbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator2) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.rbegin(), data.rend(), compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_equal) + { + const Data initial1(initial_data.begin(), initial_data.end()); + const Data initial2(initial_data.begin(), initial_data.end()); + + CHECK(initial1 == initial2); + + const Data different(different_data.begin(), different_data.end()); + + CHECK(!(initial1 == different)); + + const Data shorter(shorter_data.begin(), shorter_data.end()); + + CHECK(!(shorter == initial1)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_not_equal) + { + const Data initial1(initial_data.begin(), initial_data.end()); + const Data initial2(initial_data.begin(), initial_data.end()); + + CHECK(!(initial1 != initial2)); + + const Data different(different_data.begin(), different_data.end()); + + CHECK(initial1 != different); + + const Data shorter(shorter_data.begin(), shorter_data.end()); + + CHECK(shorter != initial1); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_ivector_of_pointer_to_pointer) + { + FPtr i1 = &f0; + etl::vector consttest; + consttest.push_back(i1); + const etl::ivector& ct = consttest; + + FPtr i2 = ct[0]; + + CHECK(i1 == i2); + } + + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + TEST(test_make_vector) + { + FPtr values[] = {&f0, &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9}; + + auto data = etl::make_vector(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9]); + + CHECK_TRUE(&f0 == data[0]); + CHECK_TRUE(&f1 == data[1]); + CHECK_TRUE(&f2 == data[2]); + CHECK_TRUE(&f3 == data[3]); + CHECK_TRUE(&f4 == data[4]); + CHECK_TRUE(&f5 == data[5]); + CHECK_TRUE(&f6 == data[6]); + CHECK_TRUE(&f7 == data[7]); + CHECK_TRUE(&f8 == data[8]); + CHECK_TRUE(&f9 == data[9]); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + Data etl_data(swap_data.begin(), swap_data.end()); + Data etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + etl::vector etl_data(4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_etl_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_functions_can_be_called) + { + Data data(initial_data.begin(), initial_data.end()); + + for (size_t i = 0; i < data.size(); ++i) + { + FPtr fptr = data[i]; + CHECK_TRUE(i * i == fptr(i)); + } + } + } +} // namespace diff --git a/test/test_vector_function_pointer_external_buffer.cpp b/test/test_vector_function_pointer_external_buffer.cpp new file mode 100644 index 00000000..4a6d5a86 --- /dev/null +++ b/test/test_vector_function_pointer_external_buffer.cpp @@ -0,0 +1,1301 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 John Wellbelove + +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 "unit_test_framework.h" + +#include +#include +#include +#include + +#include "etl/vector.h" + +namespace +{ + size_t f0(size_t a) + { + return 0 * a; + } + size_t f1(size_t a) + { + return 1 * a; + } + size_t f2(size_t a) + { + return 2 * a; + } + size_t f3(size_t a) + { + return 3 * a; + } + size_t f4(size_t a) + { + return 4 * a; + } + size_t f5(size_t a) + { + return 5 * a; + } + size_t f6(size_t a) + { + return 6 * a; + } + size_t f7(size_t a) + { + return 7 * a; + } + size_t f8(size_t a) + { + return 8 * a; + } + size_t f9(size_t a) + { + return 9 * a; + } + size_t f10(size_t a) + { + return 10 * a; + } + size_t f11(size_t a) + { + return 11 * a; + } + size_t f12(size_t a) + { + return 12 * a; + } + + SUITE(test_vector_function_pointer_external_buffer) + { + static const size_t SIZE = 10; + + using FPtr = size_t (*)(size_t); + + FPtr buffer1[SIZE]; + FPtr buffer2[SIZE]; + FPtr buffer3[SIZE]; + FPtr buffer4[SIZE]; + + using Data = etl::vector_ext; + using IData = etl::ivector; + using Compare_Data = std::vector; + + Compare_Data initial_data; + Compare_Data less_data; + Compare_Data greater_data; + Compare_Data shorter_data; + Compare_Data different_data; + Compare_Data insert_data; + Compare_Data swap_data; + Compare_Data swap_other_data; + + //************************************************************************* + struct SetupFixture + { + SetupFixture() + { + FPtr n[] = {&f0, &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9}; + FPtr n_insert[] = {&f10, &f11, &f12}; + FPtr n_less[] = {&f0, &f1, &f2, &f3, &f3, &f5, &f6, &f7, &f8, &f9}; + FPtr n_greater[] = {&f0, &f1, &f2, &f4, &f4, &f5, &f6, &f7, &f8, &f9}; + FPtr n_swap[] = {&f0, &f1, &f2, &f3, &f4, &f5}; + FPtr n_swap_other[] = {&f6, &f7, &f8, &f9}; + + initial_data.assign(std::begin(n), std::end(n)); + insert_data.assign(std::begin(n_insert), std::end(n_insert)); + less_data.assign(std::begin(n_less), std::end(n_less)); + greater_data.assign(std::begin(n_greater), std::end(n_greater)); + shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); + different_data.assign(initial_data.rbegin(), initial_data.rend()); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); + } + }; + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_default_constructor) + { + Data data(buffer1, SIZE); + + CHECK_EQUAL(data.size(), size_t(0)); + CHECK(data.empty()); + CHECK_EQUAL(data.capacity(), SIZE); + CHECK_EQUAL(data.max_size(), SIZE); + } + + //************************************************************************* + TEST(test_iterator_comparison_empty) + { + Data data(buffer1, SIZE); + + CHECK(data.begin() == data.end()); + CHECK(data.cbegin() == data.cend()); + CHECK(data.rbegin() == data.rend()); + CHECK(data.crbegin() == data.crend()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size) + { + const size_t Initial_Size = 5; + Data data(Initial_Size, buffer1, SIZE); + + CHECK(data.size() == Initial_Size); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_value) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + + CHECK(data.size() == Initial_Size); + CHECK(!data.empty()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_excess) + { + CHECK_THROW(Data data(SIZE + 1, buffer1, SIZE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + CHECK(data.size() == SIZE); + CHECK(!data.empty()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + +#if ETL_HAS_INITIALIZER_LIST + //************************************************************************* + TEST(test_constructor_initializer_list) + { + FPtr a = &f0; + FPtr b = &f1; + FPtr c = &f2; + FPtr d = &f3; + + Compare_Data compare_data = {a, b, c, d}; + Data data({a, b, c, d}, buffer1, SIZE); + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data data2(data, buffer2, SIZE); + CHECK(data2 == data); + + data2[2] = nullptr; + CHECK(data2 != data); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_constructor) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data data2(std::move(data), buffer2, SIZE); + + CHECK_EQUAL(0U, data.size()); + CHECK_EQUAL(initial_data.size(), data2.size()); + + CHECK_EQUAL(initial_data.size(), data2.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data other_data(buffer2, SIZE); + + other_data = data; + + CHECK_EQUAL(initial_data.size(), data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_from_pointer_range) + { + Data data(initial_data.data(), initial_data.data() + initial_data.size(), buffer1, SIZE); + Data other_data(buffer2, SIZE); + + other_data = data; + + CHECK_EQUAL(initial_data.size(), data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data other_data(buffer2, SIZE); + other_data.push_back(FPtr(0)); + + other_data = std::move(data); + + CHECK_EQUAL(0U, data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_iterface) + { + Data data1(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data data2(buffer2, SIZE); + + IData& idata1 = data1; + IData& idata2 = data2; + + idata2 = idata1; + + bool is_equal = std::equal(data1.begin(), data1.end(), data2.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_self_assignment) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data other_data(data, buffer2, SIZE); + +#include "etl/private/diagnostic_self_assign_overloaded_push.h" + other_data = other_data; +#include "etl/private/diagnostic_pop.h" + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_begin) + { + Data data(10, buffer1, SIZE); + const Data constData(10, buffer2, SIZE); + + CHECK_TRUE(&data[0] == data.begin()); + CHECK_TRUE(&constData[0] == constData.begin()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_end) + { + Data data(10, buffer1, SIZE); + const Data constData(10, buffer2, SIZE); + + CHECK_EQUAL(data.begin() + data.size(), data.end()); + CHECK_EQUAL(constData.begin() + constData.size(), constData.end()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 8; + + Data data(Initial_Size, buffer1, SIZE); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up_value) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 8; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + data.resize(NEW_SIZE, Initial_Value); + + std::array compare_data; + compare_data.fill(Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_excess) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = SIZE + 1; + + Data data(Initial_Size, buffer1, SIZE); + + CHECK_THROW(data.resize(NEW_SIZE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 2; + + Data data(Initial_Size, buffer1, SIZE); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down_value) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 2; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, buffer1, SIZE); + data.resize(NEW_SIZE, Initial_Value); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_empty) + { + Data data(buffer1, SIZE); + data.resize(data.max_size()); + + CHECK(data.full()); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_full) + { + Data data(buffer1, SIZE); + + CHECK(!data.full()); + CHECK(data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data[i] == compare_data[i]); + } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data[i] == compare_data[i]); + } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data.at(i) == compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data.at(i) == compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK(data.front() == compare_data.front()); + + Data emptyData(buffer2, SIZE); + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK(data.front() == compare_data.front()); + + const Data emptyData(buffer2, SIZE); + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK(data.back() == compare_data.back()); + + Data emptyData(buffer2, SIZE); + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK(data.back() == compare_data.back()); + + const Data emptyData(buffer2, SIZE); + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.data(), data.data() + data.size(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data_const) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.data(), data.data() + data.size(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(buffer1, SIZE); + + data.assign(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_size_value) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data(buffer1, SIZE); + data.assign(Initial_Size, Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_size_value_excess) + { + const size_t Initial_Size = SIZE; + const size_t EXCESS_SIZE = SIZE + 1; + FPtr Initial_Value = &f0; + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data(buffer1, SIZE); + + CHECK_THROW(data.assign(EXCESS_SIZE, Initial_Value), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + FPtr fptr = &f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + compare_data.push_back(fptr); + } + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.push_back(fptr); + } + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back_excess) + { + Data data(buffer1, SIZE); + + FPtr fptr = &f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.push_back(fptr); + } + + CHECK_THROW(data.push_back(fptr), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + FPtr fptr = &f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + compare_data.emplace_back(fptr); + } + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.emplace_back(fptr); + } + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back_return) + { + Data data(buffer1, SIZE); + FPtr fptr1 = &f0; + FPtr fptr2 = &f1; + + data.emplace_back(fptr1); + CHECK_TRUE(fptr2 == data.emplace_back(fptr2)); + } + + //************************************************************************* + TEST(test_emplace_default) + { + static FPtr initial = &f0; + + // First fill with Initial values. + etl::vector data; + data.resize(SIZE, initial); + data.clear(); + + // Then emplace Default values. + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace(data.begin()); + } + + // Compare with an array of default values. + std::array compare_data; + compare_data.fill(nullptr); + + CHECK_TRUE(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(test_emplace_back_default) + { + static FPtr initial = &f0; + + // First fill with initial values. + etl::vector data; + data.resize(SIZE, initial); + data.clear(); + + // Then emplace default values. + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace_back(); + } + + // Compare with an array of default values. + std::array compare_data; + compare_data.fill(nullptr); + + CHECK_TRUE(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + compare_data.pop_back(); + compare_data.pop_back(); + + data.pop_back(); + data.pop_back(); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back_exception) + { + Data data(buffer1, SIZE); + + data.resize(2); + + data.pop_back(); + data.pop_back(); + + CHECK_THROW(data.pop_back(), etl::vector_empty); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + + data.insert(data.begin() + offset, Initial_Value); + compare_data.insert(compare_data.begin() + static_cast(offset), Initial_Value); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + Data data(buffer1, SIZE); + Data data2(buffer2, SIZE); + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + CHECK_THROW(data.insert(data2.cbegin(), Initial_Value), etl::vector_out_of_bounds); + } + + //************************************************************************* +#include "etl/private/diagnostic_array_bounds_push.h" + TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) + { + const size_t Initial_Size = SIZE; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + + size_t offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + + offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + } +#include "etl/private/diagnostic_pop.h" + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + + data.emplace(data.begin() + offset, Initial_Value); + compare_data.emplace(compare_data.begin() + static_cast(offset), Initial_Value); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value_outofbounds) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + Data data(buffer1, SIZE); + Data data2(buffer2, SIZE); + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + CHECK_THROW(data.emplace(data2.cbegin(), Initial_Value), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value) + { + const size_t Initial_Size = 5; + const size_t INSERT_SIZE = 3; + FPtr Initial_Value = &f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value); + compare_data.insert(compare_data.begin() + static_cast(offset), INSERT_SIZE, Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + FPtr Initial_Value = &f0; + Data data(buffer1, SIZE); + Data data2(buffer2, SIZE); + + CHECK_THROW(data.insert(data2.end(), 1, Initial_Value);, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) + { + const size_t Initial_Size = SIZE; + const size_t INSERT_SIZE = 4; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range) + { + const size_t Initial_Size = 5; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.begin() + offset, insert_data.begin(), insert_data.end()); + compare_data.insert(compare_data.begin() + static_cast(offset), insert_data.begin(), insert_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_out_of_bounds) + { + Data data(buffer1, SIZE); + Data data2(buffer2, SIZE); + + CHECK_THROW(data.insert(data2.end(), insert_data.cbegin(), insert_data.cend());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_pointer_range) + { + const size_t Initial_Size = 5; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.data(), initial_data.data() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.data() + offset, insert_data.data(), insert_data.data() + insert_data.size()); + compare_data.insert(compare_data.begin() + static_cast(offset), insert_data.begin(), insert_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_pointer_range_out_of_bounds) + { + Data data(buffer1, SIZE); + + CHECK_THROW(data.insert(data.data() + data.size() + 1, insert_data.data(), insert_data.data() + insert_data.size()); + , etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) + { + const size_t Initial_Size = 5; + FPtr Initial_Value = &f0; + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + Compare_Data::iterator citr = compare_data.erase(compare_data.begin() + 2); + Data::iterator ditr = data.erase(data.begin() + 2); + + CHECK(*citr == *ditr); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK_THROW(data.erase(data.end());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + Compare_Data::iterator citr = compare_data.erase(compare_data.cbegin() + 2, compare_data.cbegin() + 4); + Data::iterator ditr = data.erase(data.cbegin() + 2, data.cbegin() + 4); + + CHECK(*citr == *ditr); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data data2(initial_data.begin(), initial_data.end(), buffer2, SIZE); + + CHECK_THROW(data.erase(data2.begin(), data2.end());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + data.clear(); + + CHECK_EQUAL(data.size(), size_t(0)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.cbegin(), data.cend(), compare_data.cbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_reverse_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.rbegin(), data.rend(), compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.crbegin(), data.crend(), compare_data.crbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator2) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.rbegin(), data.rend(), compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_equal) + { + const Data initial1(initial_data.begin(), initial_data.end(), buffer1, SIZE); + const Data initial2(initial_data.begin(), initial_data.end(), buffer2, SIZE); + + CHECK(initial1 == initial2); + + const Data different(different_data.begin(), different_data.end(), buffer3, SIZE); + + CHECK(!(initial1 == different)); + + const Data shorter(shorter_data.begin(), shorter_data.end(), buffer4, SIZE); + + CHECK(!(shorter == initial1)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_not_equal) + { + const Data initial1(initial_data.begin(), initial_data.end(), buffer1, SIZE); + const Data initial2(initial_data.begin(), initial_data.end(), buffer2, SIZE); + + CHECK(!(initial1 != initial2)); + + const Data different(different_data.begin(), different_data.end(), buffer3, SIZE); + + CHECK(initial1 != different); + + const Data shorter(shorter_data.begin(), shorter_data.end(), buffer4, SIZE); + CHECK(shorter != initial1); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_ivector_of_pointer_to_pointer) + { + FPtr i1 = &f0; + etl::vector consttest; + consttest.push_back(i1); + const etl::ivector& ct = consttest; + + FPtr i2 = ct[0]; + + CHECK(i1 == i2); + } + + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + TEST(test_make_vector) + { + FPtr values[] = {&f0, &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9}; + + auto data = etl::make_vector(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9]); + + CHECK_TRUE(&f0 == data[0]); + CHECK_TRUE(&f1 == data[1]); + CHECK_TRUE(&f2 == data[2]); + CHECK_TRUE(&f3 == data[3]); + CHECK_TRUE(&f4 == data[4]); + CHECK_TRUE(&f5 == data[5]); + CHECK_TRUE(&f6 == data[6]); + CHECK_TRUE(&f7 == data[7]); + CHECK_TRUE(&f8 == data[8]); + CHECK_TRUE(&f9 == data[9]); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + Data etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, SIZE); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + etl::vector_ext etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, other_size); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + etl::vector_ext etl_data(4, buffer1, 4); + etl::vector_ext etl_data2(6, buffer2, 6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_etl_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + etl::vector_ext etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, other_size); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_functions_can_be_called) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + for (size_t i = 0; i < data.size(); ++i) + { + FPtr fptr = data[i]; + CHECK_TRUE(i * i == fptr(i)); + } + } + } +} // namespace diff --git a/test/test_vector_member_function_pointer.cpp b/test/test_vector_member_function_pointer.cpp new file mode 100644 index 00000000..a1828db7 --- /dev/null +++ b/test/test_vector_member_function_pointer.cpp @@ -0,0 +1,1330 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 John Wellbelove + +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 "unit_test_framework.h" + +#include +#include +#include +#include + +#include "etl/vector.h" + +namespace +{ + SUITE(test_vector_member_function_pointer) + { + static const size_t SIZE = 10; + + struct Functions + { + size_t f0(size_t a) + { + return 0 * a; + } + size_t f1(size_t a) + { + return 1 * a; + } + size_t f2(size_t a) + { + return 2 * a; + } + size_t f3(size_t a) + { + return 3 * a; + } + size_t f4(size_t a) + { + return 4 * a; + } + size_t f5(size_t a) + { + return 5 * a; + } + size_t f6(size_t a) + { + return 6 * a; + } + size_t f7(size_t a) + { + return 7 * a; + } + size_t f8(size_t a) + { + return 8 * a; + } + size_t f9(size_t a) + { + return 9 * a; + } + size_t f10(size_t a) + { + return 10 * a; + } + size_t f11(size_t a) + { + return 11 * a; + } + size_t f12(size_t a) + { + return 12 * a; + } + }; + + Functions functions; + + using MFPtr = size_t (Functions::*)(size_t); + + using Data = etl::vector; + using IData = etl::ivector; + using Compare_Data = std::vector; + + Compare_Data initial_data; + Compare_Data less_data; + Compare_Data greater_data; + Compare_Data shorter_data; + Compare_Data different_data; + Compare_Data insert_data; + Compare_Data swap_data; + Compare_Data swap_other_data; + + //************************************************************************* + struct SetupFixture + { + SetupFixture() + { + MFPtr n[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + MFPtr n_insert[] = {&Functions::f10, &Functions::f11, &Functions::f12}; + MFPtr n_less[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f3, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + MFPtr n_greater[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f4, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + MFPtr n_swap[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, &Functions::f5}; + MFPtr n_swap_other[] = {&Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + + initial_data.assign(std::begin(n), std::end(n)); + insert_data.assign(std::begin(n_insert), std::end(n_insert)); + less_data.assign(std::begin(n_less), std::end(n_less)); + greater_data.assign(std::begin(n_greater), std::end(n_greater)); + shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); + different_data.assign(initial_data.rbegin(), initial_data.rend()); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); + } + }; + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_default_constructor) + { + Data data; + + CHECK_EQUAL(data.size(), size_t(0)); + CHECK(data.empty()); + CHECK_EQUAL(data.capacity(), SIZE); + CHECK_EQUAL(data.max_size(), SIZE); + } + +#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED) + //************************************************************************* + TEST(test_cpp17_deduced_constructor) + { + etl::vector data{&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + etl::vector check = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + + CHECK(!data.empty()); + CHECK(data.full()); + CHECK(data.begin() != data.end()); + CHECK_EQUAL(0U, data.available()); + CHECK_EQUAL(10U, data.capacity()); + CHECK_EQUAL(10U, data.size()); + CHECK_EQUAL(10U, data.max_size()); + CHECK(data == check); + } +#endif + + //************************************************************************* + TEST(test_iterator_comparison_empty) + { + Data data; + + CHECK(data.begin() == data.end()); + CHECK(data.cbegin() == data.cend()); + CHECK(data.rbegin() == data.rend()); + CHECK(data.crbegin() == data.crend()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size) + { + const size_t Initial_Size = 5; + Data data(Initial_Size); + + CHECK(data.size() == Initial_Size); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_value) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data(Initial_Size, Initial_Value); + + CHECK(data.size() == Initial_Size); + CHECK(!data.empty()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_excess) + { + CHECK_THROW(Data data(SIZE + 1), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + CHECK(data.size() == SIZE); + CHECK(!data.empty()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + +#if ETL_HAS_INITIALIZER_LIST + //************************************************************************* + TEST(test_constructor_initializer_list) + { + MFPtr a = &Functions::f0; + MFPtr b = &Functions::f1; + MFPtr c = &Functions::f2; + MFPtr d = &Functions::f3; + + Compare_Data compare_data = {a, b, c, d}; + Data data = {a, b, c, d}; + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + Data data(initial_data.begin(), initial_data.end()); + Data data2(data); + CHECK(data2 == data); + + data2[2] = nullptr; + CHECK(data2 != data); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_constructor) + { + Data data(initial_data.begin(), initial_data.end()); + Data data2(std::move(data)); + + CHECK_EQUAL(0U, data.size()); + CHECK_EQUAL(initial_data.size(), data2.size()); + + CHECK_EQUAL(initial_data.size(), data2.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment) + { + Data data(initial_data.begin(), initial_data.end()); + Data other_data; + + other_data = data; + + CHECK_EQUAL(initial_data.size(), data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_from_pointer_range) + { + Data data(initial_data.data(), initial_data.data() + initial_data.size()); + Data other_data; + + other_data = data; + + CHECK_EQUAL(initial_data.size(), data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + Data data(initial_data.begin(), initial_data.end()); + Data other_data; + other_data.push_back(MFPtr(0)); + + other_data = std::move(data); + + CHECK_EQUAL(0U, data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_iterface) + { + Data data1(initial_data.begin(), initial_data.end()); + Data data2; + + IData& idata1 = data1; + IData& idata2 = data2; + + idata2 = idata1; + + bool is_equal = std::equal(data1.begin(), data1.end(), data2.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_self_assignment) + { + Data data(initial_data.begin(), initial_data.end()); + Data other_data(data); + +#include "etl/private/diagnostic_self_assign_overloaded_push.h" + other_data = other_data; +#include "etl/private/diagnostic_pop.h" + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_begin) + { + Data data(10); + const Data constData(10); + + CHECK_EQUAL(&data[0], data.begin()); + CHECK_EQUAL(&constData[0], constData.begin()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_end) + { + Data data(10); + const Data constData(10); + + CHECK_EQUAL(data.begin() + data.size(), data.end()); + CHECK_EQUAL(constData.begin() + constData.size(), constData.end()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 8; + + Data data(Initial_Size); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up_value) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 8; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, Initial_Value); + data.resize(NEW_SIZE, Initial_Value); + + std::array compare_data; + compare_data.fill(Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_excess) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = SIZE + 1; + + Data data(Initial_Size); + + CHECK_THROW(data.resize(NEW_SIZE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 2; + + Data data(Initial_Size); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down_value) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 2; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size); + data.resize(NEW_SIZE, Initial_Value); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_empty) + { + Data data; + data.resize(data.max_size()); + + CHECK(data.full()); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_full) + { + Data data; + + CHECK(!data.full()); + CHECK(data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data[i] == compare_data[i]); + } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end()); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data[i] == compare_data[i]); + } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data.at(i) == compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end()); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data.at(i) == compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + CHECK(data.front() == compare_data.front()); + + Data emptyData; + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end()); + + CHECK(data.front() == compare_data.front()); + + const Data emptyData; + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + CHECK(data.back() == compare_data.back()); + + Data emptyData; + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end()); + + CHECK(data.back() == compare_data.back()); + + const Data emptyData; + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.data(), data.data() + data.size(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data_const) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.data(), data.data() + data.size(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data; + + data.assign(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_size_value) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data; + data.assign(Initial_Size, Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_size_value_excess) + { + const size_t Initial_Size = SIZE; + const size_t EXCESS_SIZE = SIZE + 1; + MFPtr Initial_Value = &Functions::f0; + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data; + + CHECK_THROW(data.assign(EXCESS_SIZE, Initial_Value), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back) + { + Compare_Data compare_data; + Data data; + + MFPtr fptr = &Functions::f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + compare_data.push_back(fptr); + } + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.push_back(fptr); + } + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back_excess) + { + Data data; + + MFPtr fptr = &Functions::f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.push_back(fptr); + } + + CHECK_THROW(data.push_back(fptr), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back) + { + Compare_Data compare_data; + Data data; + + MFPtr fptr = &Functions::f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + compare_data.emplace_back(fptr); + } + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.emplace_back(fptr); + } + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back_return) + { + Data data; + MFPtr fptr1 = &Functions::f0; + MFPtr fptr2 = &Functions::f1; + + data.emplace_back(fptr1); + CHECK_TRUE(fptr2 == data.emplace_back(fptr2)); + } + + //************************************************************************* + TEST(test_emplace_default) + { + static MFPtr initial = &Functions::f0; + + // First fill with Initial values. + etl::vector data; + data.resize(SIZE, initial); + data.clear(); + + // Then emplace Default values. + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace(data.begin()); + } + + // Compare with an array of default values. + std::array compare_data; + compare_data.fill(nullptr); + + CHECK_TRUE(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(test_emplace_back_default) + { + static MFPtr initial = &Functions::f0; + + // First fill with initial values. + etl::vector data; + data.resize(SIZE, initial); + data.clear(); + + // Then emplace default values. + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace_back(); + } + + // Compare with an array of default values. + std::array compare_data; + compare_data.fill(nullptr); + + CHECK_TRUE(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + compare_data.pop_back(); + compare_data.pop_back(); + + data.pop_back(); + data.pop_back(); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back_exception) + { + Data data; + + data.resize(2); + + data.pop_back(); + data.pop_back(); + + CHECK_THROW(data.pop_back(), etl::vector_empty); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + + data.insert(data.begin() + offset, Initial_Value); + compare_data.insert(compare_data.begin() + static_cast(offset), Initial_Value); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* +#include "etl/private/diagnostic_uninitialized_push.h" + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + Data data; + Data data2; + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + CHECK_THROW(data.insert(data2.cbegin(), Initial_Value), etl::vector_out_of_bounds); + } +#include "etl/private/diagnostic_pop.h" + + //************************************************************************* +#include "etl/private/diagnostic_array_bounds_push.h" + TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) + { + const size_t Initial_Size = SIZE; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, Initial_Value); + + size_t offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + + offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + } +#include "etl/private/diagnostic_pop.h" + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + + data.emplace(data.begin() + offset, Initial_Value); + compare_data.emplace(compare_data.begin() + static_cast(offset), Initial_Value); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* +#include "etl/private/diagnostic_uninitialized_push.h" + TEST_FIXTURE(SetupFixture, test_emplace_position_value_outofbounds) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + Data data; + Data data2; + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + CHECK_THROW(data.emplace(data2.cbegin(), Initial_Value), etl::vector_out_of_bounds); + } +#include "etl/private/diagnostic_pop.h" + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value) + { + const size_t Initial_Size = 5; + const size_t INSERT_SIZE = 3; + MFPtr Initial_Value = &Functions::f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value); + compare_data.insert(compare_data.begin() + static_cast(offset), INSERT_SIZE, Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + MFPtr Initial_Value = &Functions::f0; + Data data; + Data data2; + + CHECK_THROW(data.insert(data2.end(), 1, Initial_Value);, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) + { + const size_t Initial_Size = SIZE; + const size_t INSERT_SIZE = 4; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, Initial_Value); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range) + { + const size_t Initial_Size = 5; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.begin() + offset, insert_data.begin(), insert_data.end()); + compare_data.insert(compare_data.begin() + static_cast(offset), insert_data.begin(), insert_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_out_of_bounds) + { + Data data; + Data data2; + + CHECK_THROW(data.insert(data2.end(), insert_data.cbegin(), insert_data.cend());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_pointer_range) + { + const size_t Initial_Size = 5; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data; + + data.assign(initial_data.data(), initial_data.data() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.data() + offset, insert_data.data(), insert_data.data() + insert_data.size()); + compare_data.insert(compare_data.begin() + static_cast(offset), insert_data.begin(), insert_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_pointer_range_out_of_bounds) + { + Data data; + + CHECK_THROW(data.insert(data.data() + data.size() + 1, insert_data.data(), insert_data.data() + insert_data.size()); + , etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, Initial_Value); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + Compare_Data::iterator citr = compare_data.erase(compare_data.begin() + 2); + Data::iterator ditr = data.erase(data.begin() + 2); + + CHECK(*citr == *ditr); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Data data(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.erase(data.end());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end()); + + Compare_Data::iterator citr = compare_data.erase(compare_data.cbegin() + 2, compare_data.cbegin() + 4); + Data::iterator ditr = data.erase(data.cbegin() + 2, data.cbegin() + 4); + + CHECK(*citr == *ditr); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Data data(initial_data.begin(), initial_data.end()); + Data data2(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.erase(data2.begin(), data2.end());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + data.clear(); + + CHECK_EQUAL(data.size(), size_t(0)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.cbegin(), data.cend(), compare_data.cbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_reverse_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.rbegin(), data.rend(), compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.crbegin(), data.crend(), compare_data.crbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator2) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.rbegin(), data.rend(), compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_equal) + { + const Data initial1(initial_data.begin(), initial_data.end()); + const Data initial2(initial_data.begin(), initial_data.end()); + + CHECK(initial1 == initial2); + + const Data different(different_data.begin(), different_data.end()); + + CHECK(!(initial1 == different)); + + const Data shorter(shorter_data.begin(), shorter_data.end()); + + CHECK(!(shorter == initial1)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_not_equal) + { + const Data initial1(initial_data.begin(), initial_data.end()); + const Data initial2(initial_data.begin(), initial_data.end()); + + CHECK(!(initial1 != initial2)); + + const Data different(different_data.begin(), different_data.end()); + + CHECK(initial1 != different); + + const Data shorter(shorter_data.begin(), shorter_data.end()); + + CHECK(shorter != initial1); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_ivector_of_pointer_to_pointer) + { + MFPtr i1 = &Functions::f0; + etl::vector consttest; + consttest.push_back(i1); + const etl::ivector& ct = consttest; + + MFPtr i2 = ct[0]; + + CHECK(i1 == i2); + } + + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + TEST(test_make_vector) + { + MFPtr values[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + + auto data = etl::make_vector(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9]); + + CHECK_TRUE(&Functions::f0 == data[0]); + CHECK_TRUE(&Functions::f1 == data[1]); + CHECK_TRUE(&Functions::f2 == data[2]); + CHECK_TRUE(&Functions::f3 == data[3]); + CHECK_TRUE(&Functions::f4 == data[4]); + CHECK_TRUE(&Functions::f5 == data[5]); + CHECK_TRUE(&Functions::f6 == data[6]); + CHECK_TRUE(&Functions::f7 == data[7]); + CHECK_TRUE(&Functions::f8 == data[8]); + CHECK_TRUE(&Functions::f9 == data[9]); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + Data etl_data(swap_data.begin(), swap_data.end()); + Data etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + etl::vector etl_data(4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_etl_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_functions_can_be_called) + { + Data data(initial_data.begin(), initial_data.end()); + + for (size_t i = 0; i < data.size(); ++i) + { + MFPtr mfptr = data[i]; + CHECK_TRUE(i * i == (functions.*mfptr)(i)); + } + } + } +} // namespace diff --git a/test/test_vector_member_function_pointer_external_buffer.cpp b/test/test_vector_member_function_pointer_external_buffer.cpp new file mode 100644 index 00000000..644fbf92 --- /dev/null +++ b/test/test_vector_member_function_pointer_external_buffer.cpp @@ -0,0 +1,1329 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 John Wellbelove + +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 "unit_test_framework.h" + +#include +#include +#include +#include + +#include "etl/vector.h" + +namespace +{ + SUITE(test_vector_member_function_pointer_external_buffer) + { + static const size_t SIZE = 10; + + struct Functions + { + size_t f0(size_t a) + { + return 0 * a; + } + size_t f1(size_t a) + { + return 1 * a; + } + size_t f2(size_t a) + { + return 2 * a; + } + size_t f3(size_t a) + { + return 3 * a; + } + size_t f4(size_t a) + { + return 4 * a; + } + size_t f5(size_t a) + { + return 5 * a; + } + size_t f6(size_t a) + { + return 6 * a; + } + size_t f7(size_t a) + { + return 7 * a; + } + size_t f8(size_t a) + { + return 8 * a; + } + size_t f9(size_t a) + { + return 9 * a; + } + size_t f10(size_t a) + { + return 10 * a; + } + size_t f11(size_t a) + { + return 11 * a; + } + size_t f12(size_t a) + { + return 12 * a; + } + }; + + Functions functions; + + using MFPtr = size_t (Functions::*)(size_t); + + MFPtr buffer1[SIZE]; + MFPtr buffer2[SIZE]; + MFPtr buffer3[SIZE]; + MFPtr buffer4[SIZE]; + + using Data = etl::vector_ext; + using IData = etl::ivector; + using Compare_Data = std::vector; + + Compare_Data initial_data; + Compare_Data less_data; + Compare_Data greater_data; + Compare_Data shorter_data; + Compare_Data different_data; + Compare_Data insert_data; + Compare_Data swap_data; + Compare_Data swap_other_data; + + //************************************************************************* + struct SetupFixture + { + SetupFixture() + { + MFPtr n[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + MFPtr n_insert[] = {&Functions::f10, &Functions::f11, &Functions::f12}; + MFPtr n_less[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f3, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + MFPtr n_greater[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f4, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + MFPtr n_swap[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, &Functions::f5}; + MFPtr n_swap_other[] = {&Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + + initial_data.assign(std::begin(n), std::end(n)); + insert_data.assign(std::begin(n_insert), std::end(n_insert)); + less_data.assign(std::begin(n_less), std::end(n_less)); + greater_data.assign(std::begin(n_greater), std::end(n_greater)); + shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); + different_data.assign(initial_data.rbegin(), initial_data.rend()); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); + } + }; + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_default_constructor) + { + Data data(buffer1, SIZE); + + CHECK_EQUAL(data.size(), size_t(0)); + CHECK(data.empty()); + CHECK_EQUAL(data.capacity(), SIZE); + CHECK_EQUAL(data.max_size(), SIZE); + } + +#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED) + //************************************************************************* + TEST(test_cpp17_deduced_constructor) + { + etl::vector data{&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + etl::vector check = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + + CHECK(!data.empty()); + CHECK(data.full()); + CHECK(data.begin() != data.end()); + CHECK_EQUAL(0U, data.available()); + CHECK_EQUAL(10U, data.capacity()); + CHECK_EQUAL(10U, data.size()); + CHECK_EQUAL(10U, data.max_size()); + CHECK(data == check); + } +#endif + + //************************************************************************* + TEST(test_iterator_comparison_empty) + { + Data data(buffer1, SIZE); + + CHECK(data.begin() == data.end()); + CHECK(data.cbegin() == data.cend()); + CHECK(data.rbegin() == data.rend()); + CHECK(data.crbegin() == data.crend()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size) + { + const size_t Initial_Size = 5; + Data data(Initial_Size, buffer1, SIZE); + + CHECK(data.size() == Initial_Size); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_value) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + + CHECK(data.size() == Initial_Size); + CHECK(!data.empty()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_excess) + { + CHECK_THROW(Data data(SIZE + 1, buffer1, SIZE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + CHECK(data.size() == SIZE); + CHECK(!data.empty()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + +#if ETL_HAS_INITIALIZER_LIST + //************************************************************************* + TEST(test_constructor_initializer_list) + { + MFPtr a = &Functions::f0; + MFPtr b = &Functions::f1; + MFPtr c = &Functions::f2; + MFPtr d = &Functions::f3; + + Compare_Data compare_data = {a, b, c, d}; + Data data({a, b, c, d}, buffer1, SIZE); + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data data2(data, buffer2, SIZE); + CHECK(data2 == data); + + data2[2] = nullptr; + CHECK(data2 != data); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_constructor) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data data2(std::move(data), buffer2, SIZE); + + CHECK_EQUAL(0U, data.size()); + CHECK_EQUAL(initial_data.size(), data2.size()); + + CHECK_EQUAL(initial_data.size(), data2.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data other_data(buffer2, SIZE); + + other_data = data; + + CHECK_EQUAL(initial_data.size(), data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_from_pointer_range) + { + Data data(initial_data.data(), initial_data.data() + initial_data.size(), buffer1, SIZE); + Data other_data(buffer2, SIZE); + + other_data = data; + + CHECK_EQUAL(initial_data.size(), data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data other_data(buffer2, SIZE); + other_data.push_back(MFPtr(0)); + + other_data = std::move(data); + + CHECK_EQUAL(0U, data.size()); + CHECK_EQUAL(initial_data.size(), other_data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_iterface) + { + Data data1(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data data2(buffer2, SIZE); + + IData& idata1 = data1; + IData& idata2 = data2; + + idata2 = idata1; + + bool is_equal = std::equal(data1.begin(), data1.end(), data2.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_self_assignment) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data other_data(data, buffer2, SIZE); + +#include "etl/private/diagnostic_self_assign_overloaded_push.h" + other_data = other_data; +#include "etl/private/diagnostic_pop.h" + + bool is_equal = std::equal(data.begin(), data.end(), other_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_begin) + { + Data data(10, buffer1, SIZE); + const Data constData(10, buffer2, SIZE); + + CHECK_TRUE(&data[0] == data.begin()); + CHECK_TRUE(&constData[0] == constData.begin()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_end) + { + Data data(10, buffer1, SIZE); + const Data constData(10, buffer2, SIZE); + + CHECK_EQUAL(data.begin() + data.size(), data.end()); + CHECK_EQUAL(constData.begin() + constData.size(), constData.end()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 8; + + Data data(Initial_Size, buffer1, SIZE); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up_value) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 8; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + data.resize(NEW_SIZE, Initial_Value); + + std::array compare_data; + compare_data.fill(Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_excess) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = SIZE + 1; + + Data data(Initial_Size, buffer1, SIZE); + + CHECK_THROW(data.resize(NEW_SIZE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 2; + + Data data(Initial_Size, buffer1, SIZE); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down_value) + { + const size_t Initial_Size = 5; + const size_t NEW_SIZE = 2; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, buffer1, SIZE); + data.resize(NEW_SIZE, Initial_Value); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_empty) + { + Data data(buffer1, SIZE); + data.resize(data.max_size()); + + CHECK(data.full()); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_full) + { + Data data(buffer1, SIZE); + + CHECK(!data.full()); + CHECK(data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data[i] == compare_data[i]); + } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data[i] == compare_data[i]); + } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data.at(i) == compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + for (size_t i = 0UL; i < data.size(); ++i) + { + CHECK_TRUE(data.at(i) == compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK(data.front() == compare_data.front()); + + Data emptyData(buffer2, SIZE); + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK(data.front() == compare_data.front()); + + const Data emptyData(buffer2, SIZE); + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK(data.back() == compare_data.back()); + + Data emptyData(buffer2, SIZE); + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back_const) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + const Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK(data.back() == compare_data.back()); + + const Data emptyData(buffer2, SIZE); + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.data(), data.data() + data.size(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data_const) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.data(), data.data() + data.size(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(buffer1, SIZE); + + data.assign(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_size_value) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data(buffer1, SIZE); + data.assign(Initial_Size, Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_size_value_excess) + { + const size_t Initial_Size = SIZE; + const size_t EXCESS_SIZE = SIZE + 1; + MFPtr Initial_Value = &Functions::f0; + std::array compare_data; + compare_data.fill(Initial_Value); + + Data data(buffer1, SIZE); + + CHECK_THROW(data.assign(EXCESS_SIZE, Initial_Value), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + MFPtr fptr = &Functions::f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + compare_data.push_back(fptr); + } + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.push_back(fptr); + } + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back_excess) + { + Data data(buffer1, SIZE); + + MFPtr fptr = &Functions::f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.push_back(fptr); + } + + CHECK_THROW(data.push_back(fptr), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + MFPtr fptr = &Functions::f0; + + for (size_t i = 0UL; i < SIZE; ++i) + { + compare_data.emplace_back(fptr); + } + + for (size_t i = 0UL; i < SIZE; ++i) + { + data.emplace_back(fptr); + } + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back_return) + { + Data data(buffer1, SIZE); + MFPtr fptr1 = &Functions::f0; + MFPtr fptr2 = &Functions::f1; + + data.emplace_back(fptr1); + CHECK_TRUE(fptr2 == data.emplace_back(fptr2)); + } + + //************************************************************************* + TEST(test_emplace_default) + { + static MFPtr initial = &Functions::f0; + + // First fill with Initial values. + etl::vector data; + data.resize(SIZE, initial); + data.clear(); + + // Then emplace Default values. + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace(data.begin()); + } + + // Compare with an array of default values. + std::array compare_data; + compare_data.fill(nullptr); + + CHECK_TRUE(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(test_emplace_back_default) + { + static MFPtr initial = &Functions::f0; + + // First fill with initial values. + etl::vector data; + data.resize(SIZE, initial); + data.clear(); + + // Then emplace default values. + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace_back(); + } + + // Compare with an array of default values. + std::array compare_data; + compare_data.fill(nullptr); + + CHECK_TRUE(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + compare_data.pop_back(); + compare_data.pop_back(); + + data.pop_back(); + data.pop_back(); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back_exception) + { + Data data(buffer1, SIZE); + + data.resize(2); + + data.pop_back(); + data.pop_back(); + + CHECK_THROW(data.pop_back(), etl::vector_empty); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + + data.insert(data.begin() + offset, Initial_Value); + compare_data.insert(compare_data.begin() + static_cast(offset), Initial_Value); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + Data data(buffer1, SIZE); + Data data2(buffer2, SIZE); + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + CHECK_THROW(data.insert(data2.cbegin(), Initial_Value), etl::vector_out_of_bounds); + } + + //************************************************************************* +#include "etl/private/diagnostic_array_bounds_push.h" + TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) + { + const size_t Initial_Size = SIZE; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + + size_t offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + + offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, Initial_Value), etl::vector_full); + } +#include "etl/private/diagnostic_pop.h" + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + + data.emplace(data.begin() + offset, Initial_Value); + compare_data.emplace(compare_data.begin() + static_cast(offset), Initial_Value); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value_outofbounds) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + Data data(buffer1, SIZE); + Data data2(buffer2, SIZE); + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + CHECK_THROW(data.emplace(data2.cbegin(), Initial_Value), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value) + { + const size_t Initial_Size = 5; + const size_t INSERT_SIZE = 3; + MFPtr Initial_Value = &Functions::f0; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value); + compare_data.insert(compare_data.begin() + static_cast(offset), INSERT_SIZE, Initial_Value); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + MFPtr Initial_Value = &Functions::f0; + Data data(buffer1, SIZE); + Data data2(buffer2, SIZE); + + CHECK_THROW(data.insert(data2.end(), 1, Initial_Value);, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) + { + const size_t Initial_Size = SIZE; + const size_t INSERT_SIZE = 4; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, Initial_Value), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range) + { + const size_t Initial_Size = 5; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.begin() + offset, insert_data.begin(), insert_data.end()); + compare_data.insert(compare_data.begin() + static_cast(offset), insert_data.begin(), insert_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_out_of_bounds) + { + Data data(buffer1, SIZE); + Data data2(buffer2, SIZE); + + CHECK_THROW(data.insert(data2.end(), insert_data.cbegin(), insert_data.cend());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_pointer_range) + { + const size_t Initial_Size = 5; + + for (size_t offset = 0; offset <= Initial_Size; ++offset) + { + Compare_Data compare_data; + Data data(buffer1, SIZE); + + data.assign(initial_data.data(), initial_data.data() + Initial_Size); + compare_data.assign(initial_data.begin(), initial_data.begin() + Initial_Size); + data.insert(data.data() + offset, insert_data.data(), insert_data.data() + insert_data.size()); + compare_data.insert(compare_data.begin() + static_cast(offset), insert_data.begin(), insert_data.end()); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_pointer_range_out_of_bounds) + { + Data data(buffer1, SIZE); + + CHECK_THROW(data.insert(data.data() + data.size() + 1, insert_data.data(), insert_data.data() + insert_data.size()); + , etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) + { + const size_t Initial_Size = 5; + MFPtr Initial_Value = &Functions::f0; + + Data data(Initial_Size, Initial_Value, buffer1, SIZE); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + Compare_Data::iterator citr = compare_data.erase(compare_data.begin() + 2); + Data::iterator ditr = data.erase(data.begin() + 2); + + CHECK(*citr == *ditr); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + CHECK_THROW(data.erase(data.end());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data(initial_data.begin(), initial_data.end(), buffer2, SIZE); + + Compare_Data::iterator citr = compare_data.erase(compare_data.cbegin() + 2, compare_data.cbegin() + 4); + Data::iterator ditr = data.erase(data.cbegin() + 2, data.cbegin() + 4); + + CHECK(*citr == *ditr); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + Data data2(initial_data.begin(), initial_data.end(), buffer2, SIZE); + + CHECK_THROW(data.erase(data2.begin(), data2.end());, etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + data.clear(); + + CHECK_EQUAL(data.size(), size_t(0)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.cbegin(), data.cend(), compare_data.cbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_reverse_iterator) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.rbegin(), data.rend(), compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.crbegin(), data.crend(), compare_data.crbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator2) + { + const Compare_Data compare_data(initial_data.begin(), initial_data.end()); + + const Data data(compare_data.begin(), compare_data.end(), buffer1, SIZE); + + bool is_equal = std::equal(data.rbegin(), data.rend(), compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_equal) + { + const Data initial1(initial_data.begin(), initial_data.end(), buffer1, SIZE); + const Data initial2(initial_data.begin(), initial_data.end(), buffer2, SIZE); + + CHECK(initial1 == initial2); + + const Data different(different_data.begin(), different_data.end(), buffer3, SIZE); + + CHECK(!(initial1 == different)); + + const Data shorter(shorter_data.begin(), shorter_data.end(), buffer4, SIZE); + CHECK(!(shorter == initial1)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_not_equal) + { + const Data initial1(initial_data.begin(), initial_data.end(), buffer1, SIZE); + const Data initial2(initial_data.begin(), initial_data.end(), buffer2, SIZE); + + CHECK(!(initial1 != initial2)); + + const Data different(different_data.begin(), different_data.end(), buffer3, SIZE); + + CHECK(initial1 != different); + + const Data shorter(shorter_data.begin(), shorter_data.end(), buffer4, SIZE); + CHECK(shorter != initial1); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_ivector_of_pointer_to_pointer) + { + MFPtr i1 = &Functions::f0; + etl::vector consttest; + consttest.push_back(i1); + const etl::ivector& ct = consttest; + + MFPtr i2 = ct[0]; + + CHECK(i1 == i2); + } + + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + TEST(test_make_vector) + { + MFPtr values[] = {&Functions::f0, &Functions::f1, &Functions::f2, &Functions::f3, &Functions::f4, + &Functions::f5, &Functions::f6, &Functions::f7, &Functions::f8, &Functions::f9}; + + auto data = etl::make_vector(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9]); + + CHECK_TRUE(&Functions::f0 == data[0]); + CHECK_TRUE(&Functions::f1 == data[1]); + CHECK_TRUE(&Functions::f2 == data[2]); + CHECK_TRUE(&Functions::f3 == data[3]); + CHECK_TRUE(&Functions::f4 == data[4]); + CHECK_TRUE(&Functions::f5 == data[5]); + CHECK_TRUE(&Functions::f6 == data[6]); + CHECK_TRUE(&Functions::f7 == data[7]); + CHECK_TRUE(&Functions::f8 == data[8]); + CHECK_TRUE(&Functions::f9 == data[9]); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + Data etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, SIZE); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + etl::vector_ext etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, other_size); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + etl::vector_ext etl_data(4, buffer1, 4); + etl::vector_ext etl_data2(6, buffer2, 6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_etl_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + etl::vector_ext etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, other_size); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_functions_can_be_called) + { + Data data(initial_data.begin(), initial_data.end(), buffer1, SIZE); + + for (size_t i = 0; i < data.size(); ++i) + { + MFPtr mfptr = data[i]; + CHECK_TRUE(i * i == (functions.*mfptr)(i)); + } + } + } +} // namespace diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index e4b0e1cf..99037eb2 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3700,7 +3700,6 @@ - @@ -11462,6 +11461,10 @@ + + + + @@ -11497,19 +11500,32 @@ + + + + + + + + + + + + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index d305c89c..55c17cab 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -597,9 +597,6 @@ ETL\Utilities - - ETL\Private - ETL\Private @@ -1569,6 +1566,9 @@ ETL\Messaging\Generators + + UnitTest++\Header Files + @@ -3815,6 +3815,18 @@ Tests\Callbacks & Delegates + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + @@ -3999,6 +4011,45 @@ Tests\Scripts + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github + + + Resource Files\CI\Github +