diff --git a/Modules/Core/Common/include/itkFixedArray.h b/Modules/Core/Common/include/itkFixedArray.h index 76634b8ce89..f0bb58d9cd4 100644 --- a/Modules/Core/Common/include/itkFixedArray.h +++ b/Modules/Core/Common/include/itkFixedArray.h @@ -322,37 +322,37 @@ class ITK_TEMPLATE_EXPORT FixedArray itkLegacyMacro(ConstReverseIterator rEnd() const); - const_iterator + constexpr const_iterator cbegin() const noexcept { return m_InternalArray; } - iterator + constexpr iterator begin() noexcept { return m_InternalArray; } - const_iterator + constexpr const_iterator begin() const noexcept { return this->cbegin(); } - const_iterator + constexpr const_iterator cend() const noexcept { return m_InternalArray + VLength; } - iterator + constexpr iterator end() noexcept { return m_InternalArray + VLength; } - const_iterator + constexpr const_iterator end() const noexcept { return this->cend(); diff --git a/Modules/Core/Common/include/itkIndex.h b/Modules/Core/Common/include/itkIndex.h index 31d10ca70cb..258fff85cd7 100644 --- a/Modules/Core/Common/include/itkIndex.h +++ b/Modules/Core/Common/include/itkIndex.h @@ -346,28 +346,40 @@ struct ITK_TEMPLATE_EXPORT Index final std::swap(m_InternalArray, other.m_InternalArray); } - iterator + constexpr const_iterator + cbegin() const + { + return &m_InternalArray[0]; + } + + constexpr iterator begin() { - return iterator(&m_InternalArray[0]); + return &m_InternalArray[0]; } - const_iterator + constexpr const_iterator begin() const { - return const_iterator(&m_InternalArray[0]); + return &m_InternalArray[0]; + } + + constexpr const_iterator + cend() const + { + return &m_InternalArray[VDimension]; } - iterator + constexpr iterator end() { - return iterator(&m_InternalArray[VDimension]); + return &m_InternalArray[VDimension]; } - const_iterator + constexpr const_iterator end() const { - return const_iterator(&m_InternalArray[VDimension]); + return &m_InternalArray[VDimension]; } reverse_iterator diff --git a/Modules/Core/Common/include/itkOffset.h b/Modules/Core/Common/include/itkOffset.h index 325e546b6fb..ae71c8b4daa 100644 --- a/Modules/Core/Common/include/itkOffset.h +++ b/Modules/Core/Common/include/itkOffset.h @@ -299,28 +299,40 @@ struct ITK_TEMPLATE_EXPORT Offset final std::swap(m_InternalArray, other.m_InternalArray); } - iterator + constexpr const_iterator + cbegin() const + { + return &m_InternalArray[0]; + } + + constexpr iterator begin() { - return iterator(&m_InternalArray[0]); + return &m_InternalArray[0]; } - const_iterator + constexpr const_iterator begin() const { - return const_iterator(&m_InternalArray[0]); + return &m_InternalArray[0]; + } + + constexpr const_iterator + cend() const + { + return &m_InternalArray[VDimension]; } - iterator + constexpr iterator end() { - return iterator(&m_InternalArray[VDimension]); + return &m_InternalArray[VDimension]; } - const_iterator + constexpr const_iterator end() const { - return const_iterator(&m_InternalArray[VDimension]); + return &m_InternalArray[VDimension]; } reverse_iterator diff --git a/Modules/Core/Common/include/itkSize.h b/Modules/Core/Common/include/itkSize.h index db55676dee1..7e56390a625 100644 --- a/Modules/Core/Common/include/itkSize.h +++ b/Modules/Core/Common/include/itkSize.h @@ -258,28 +258,40 @@ struct ITK_TEMPLATE_EXPORT Size final std::swap(m_InternalArray, other.m_InternalArray); } - iterator + constexpr const_iterator + cbegin() const + { + return &m_InternalArray[0]; + } + + constexpr iterator begin() { - return iterator(&m_InternalArray[0]); + return &m_InternalArray[0]; } - const_iterator + constexpr const_iterator begin() const { - return const_iterator(&m_InternalArray[0]); + return &m_InternalArray[0]; + } + + constexpr const_iterator + cend() const + { + return &m_InternalArray[VDimension]; } - iterator + constexpr iterator end() { - return iterator(&m_InternalArray[VDimension]); + return &m_InternalArray[VDimension]; } - const_iterator + constexpr const_iterator end() const { - return const_iterator(&m_InternalArray[VDimension]); + return &m_InternalArray[VDimension]; } reverse_iterator diff --git a/Modules/Core/Common/test/CMakeLists.txt b/Modules/Core/Common/test/CMakeLists.txt index fc40d9525a4..3f62d2eed2d 100644 --- a/Modules/Core/Common/test/CMakeLists.txt +++ b/Modules/Core/Common/test/CMakeLists.txt @@ -624,6 +624,7 @@ set(ITKCommonGTests itkMersenneTwisterRandomVariateGeneratorGTest.cxx itkNeighborhoodAllocatorGTest.cxx itkNumberToStringGTest.cxx + itkOffsetGTest.cxx itkOptimizerParametersGTest.cxx itkPointGTest.cxx itkShapedImageNeighborhoodRangeGTest.cxx diff --git a/Modules/Core/Common/test/itkFixedArrayGTest.cxx b/Modules/Core/Common/test/itkFixedArrayGTest.cxx index ac6d94155e0..7d46249c6fc 100644 --- a/Modules/Core/Common/test/itkFixedArrayGTest.cxx +++ b/Modules/Core/Common/test/itkFixedArrayGTest.cxx @@ -21,6 +21,7 @@ // First include the header file to be tested: #include "itkFixedArray.h" +#include "itkRangeGTestUtilities.h" #include #include @@ -248,6 +249,10 @@ static_assert(Is_Filled_FixedArray_correctly_filled<0>() && Is_Filled_FixedArray Is_Filled_FixedArray_correctly_filled::max()>(), "itk::FixedArray::Filled(value) should be correctly filled at compile-time"); +static_assert(itk::RangeGTestUtilities::CheckConstexprBeginAndEndOfContainer>() && + itk::RangeGTestUtilities::CheckConstexprBeginAndEndOfContainer>(), + "Check constexpr begin() and end() of FixedArray."); + // Tests that the values of a FixedArray (either const or non-const) can be retrieved by a // range-based for-loop. diff --git a/Modules/Core/Common/test/itkIndexGTest.cxx b/Modules/Core/Common/test/itkIndexGTest.cxx index 90678e8dbdf..bd8653ae2bd 100644 --- a/Modules/Core/Common/test/itkIndexGTest.cxx +++ b/Modules/Core/Common/test/itkIndexGTest.cxx @@ -18,6 +18,7 @@ // First include the header file to be tested: #include "itkIndex.h" +#include "itkRangeGTestUtilities.h" #include #include #include @@ -70,6 +71,10 @@ static_assert(Is_Filled_Index_correctly_filled<0>() && Is_Filled_Index_correctly Is_Filled_Index_correctly_filled::max()>(), "itk::Index::Filled(value) should be correctly filled at compile-time"); +static_assert(itk::RangeGTestUtilities::CheckConstexprBeginAndEndOfContainer>() && + itk::RangeGTestUtilities::CheckConstexprBeginAndEndOfContainer>(), + "Check constexpr begin() and end() of Index."); + // Tests that itk::Index::Filled(value) returns an itk::Index with the // specified value for each element. diff --git a/Modules/Core/Common/test/itkOffsetGTest.cxx b/Modules/Core/Common/test/itkOffsetGTest.cxx new file mode 100644 index 00000000000..ce8931e617c --- /dev/null +++ b/Modules/Core/Common/test/itkOffsetGTest.cxx @@ -0,0 +1,26 @@ +/*========================================================================= + * + * Copyright NumFOCUS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +// First include the header file to be tested: +#include "itkOffset.h" +#include "itkRangeGTestUtilities.h" + + +static_assert(itk::RangeGTestUtilities::CheckConstexprBeginAndEndOfContainer>() && + itk::RangeGTestUtilities::CheckConstexprBeginAndEndOfContainer>(), + "Check constexpr begin() and end() of Offset."); diff --git a/Modules/Core/Common/test/itkRangeGTestUtilities.h b/Modules/Core/Common/test/itkRangeGTestUtilities.h index 3c46be861fe..8ccbff23a3b 100644 --- a/Modules/Core/Common/test/itkRangeGTestUtilities.h +++ b/Modules/Core/Common/test/itkRangeGTestUtilities.h @@ -103,6 +103,40 @@ class RangeGTestUtilities ExpectRangesHaveEqualBeginAndEnd(moveAssignedRange, originalRangeBeforeMove); } + + // Checks the `constexpr` member functions begin() and end() of a container like FixedArray, Index, Offset and Size. + template + static constexpr bool + CheckConstexprBeginAndEndOfContainer() + { + using ConstContainerType = const TContainer; + using ValueType = std::remove_reference_t; + + static_assert(std::is_same::value, + "For a non-const container, begin() should return a non-const reference"); + static_assert(std::is_same::value, + "For a const container, begin() should return a const reference"); + static_assert(std::is_same::value && + std::is_same::value, + "For any container, cbegin() should return a const reference"); + + static_assert(std::is_same::value, + "For a non-const container, end() should return a non-const reference"); + static_assert(std::is_same::value, + "For a const container, end() should return a const reference"); + static_assert(std::is_same::value && + std::is_same::value, + "For any container, cend() should return a const reference"); + + constexpr TContainer container{}; + + static_assert(container.cbegin() == container.begin(), "cbegin() should return the same iterator as begin()."); + static_assert(container.cend() == container.end(), "cend() should return the same iterator as end()."); + + // Just return true to ease calling this function inside a static_assert. + return true; + } + private: template static void diff --git a/Modules/Core/Common/test/itkSizeGTest.cxx b/Modules/Core/Common/test/itkSizeGTest.cxx index f4ad3cc4ea6..68967ed9b09 100644 --- a/Modules/Core/Common/test/itkSizeGTest.cxx +++ b/Modules/Core/Common/test/itkSizeGTest.cxx @@ -18,6 +18,7 @@ // First include the header file to be tested: #include "itkSize.h" +#include "itkRangeGTestUtilities.h" #include #include #include // For integral_constant. @@ -75,6 +76,10 @@ static_assert(Is_Filled_Size_correctly_filled<0>() && Is_Filled_Size_correctly_f Is_Filled_Size_correctly_filled::max()>(), "itk::Size::Filled(value) should be correctly filled at compile-time"); +static_assert(itk::RangeGTestUtilities::CheckConstexprBeginAndEndOfContainer>() && + itk::RangeGTestUtilities::CheckConstexprBeginAndEndOfContainer>(), + "Check constexpr begin() and end() of Size."); + // Tests that itk::Size::Filled(value) returns an itk::Size with the // specified value for each element.