diff --git a/auxi/impl_algo.h b/auxi/impl_algo.h index 62d0be2c..8280be72 100644 --- a/auxi/impl_algo.h +++ b/auxi/impl_algo.h @@ -7,7 +7,7 @@ #include "contiguous_iterator_to_ptr.h" -#include "range_traits.h" +#include "util.h" // for as_unsigned #include @@ -88,11 +88,11 @@ namespace oel::_detail if constexpr (std::is_trivial_v and sizeof...(Args) == 0) { - std::memset(first, 0, sizeof(T) * (last - first)); + std::memset(first, 0, sizeof(T) * as_unsigned(last - first)); } else if constexpr (isByte) { - std::memset(first, static_cast(args)..., last - first); + std::memset(first, static_cast(args)..., as_unsigned(last - first)); } else { T *const init = first; diff --git a/auxi/range_algo_detail.h b/auxi/range_algo_detail.h index 772de714..f57533d4 100644 --- a/auxi/range_algo_detail.h +++ b/auxi/range_algo_detail.h @@ -52,8 +52,8 @@ namespace oel::_detail //////////////////////////////////////////////////////////////////////////////// - template< typename InputIter, typename RandomAccessIter > - InputIter CopyUnsf(InputIter src, size_t const n, RandomAccessIter const dest) + template< typename InputIter, typename Integral, typename RandomAccessIter > + InputIter CopyUnsf(InputIter src, Integral const n, RandomAccessIter const dest) { if constexpr (can_memmove_with) { @@ -64,11 +64,11 @@ namespace oel::_detail (void) *(dest + (n - 1)); } #endif - _detail::MemcpyCheck(src, n, to_pointer_contiguous(dest)); + _detail::MemcpyCheck(src, as_unsigned(n), to_pointer_contiguous(dest)); return src + n; } else - { for (size_t i{}; i < n; ++i) + { for (Integral i{}; i < n; ++i) { dest[i] = *src; ++src; diff --git a/dynarray.h b/dynarray.h index 63d69c78..c809a14c 100644 --- a/dynarray.h +++ b/dynarray.h @@ -206,9 +206,9 @@ class dynarray [[nodiscard]] bool empty() const noexcept { return _m.data == _m.end; } - size_type size() const noexcept { return _m.end - _m.data; } + size_type size() const noexcept { return static_cast(_m.end - _m.data); } - size_type capacity() const noexcept { return _m.reservEnd - _m.data; } + size_type capacity() const noexcept { return static_cast(_m.reservEnd - _m.data); } constexpr size_type max_size() const noexcept { return _alloTrait::max_size(_m) - _allocateWrap::sizeForHeader; } @@ -242,15 +242,21 @@ class dynarray T & back() noexcept { return *_detail::MakeDynarrIter (_m, _m.end - 1); } const T & back() const noexcept { return *_detail::MakeDynarrIter(_m, _m.end - 1); } + T & operator[](size_type index) noexcept { OEL_ASSERT(index < size()); return _m.data[index]; } + const T & operator[](size_type index) const noexcept { OEL_ASSERT(index < size()); return _m.data[index]; } + T & at(size_type index) OEL_ALWAYS_INLINE { const auto & cSelf = *this; return const_cast(cSelf.at(index)); } - const T & at(size_type index) const; - - T & operator[](size_type index) noexcept { OEL_ASSERT(index < size()); return _m.data[index]; } - const T & operator[](size_type index) const noexcept { OEL_ASSERT(index < size()); return _m.data[index]; } + const T & at(size_type index) const + { + if (index < size()) // would be unsafe with signed size_type + return _m.data[index]; + else + _detail::OutOfRange::raise("Bad index dynarray::at"); + } friend bool operator==(const dynarray & left, const dynarray & right) { @@ -290,7 +296,7 @@ class dynarray : ::oel::_detail::DynarrBase{}, _usedAlloc_7KQw{std::move(a)} { } - _memOwner(_memOwner && other) noexcept + constexpr _memOwner(_memOwner && other) noexcept : ::oel::_detail::DynarrBase{other}, _usedAlloc_7KQw{std::move(other)} { other.reservEnd = other.end = other.data = nullptr; @@ -299,7 +305,10 @@ class dynarray ~_memOwner() { if (data) - ::oel::_detail::DebugAllocateWrapper<_usedAlloc_7KQw, value_type *>::dealloc(*this, data, reservEnd - data); + { + ::oel::_detail::DebugAllocateWrapper<_usedAlloc_7KQw, value_type *> + ::dealloc(*this, data, static_cast(reservEnd - data)); + } } } _m; // the only non-static data member @@ -330,7 +339,7 @@ class dynarray size_type _unusedCapacity() const { - return _m.reservEnd - _m.end; + return static_cast(_m.reservEnd - _m.end); } size_type _calcCapUnchecked(size_type const newSize) const @@ -375,13 +384,13 @@ class dynarray { if constexpr (allocator_can_realloc) { - T *const p = _allocateWrap::realloc(_m, _m.data, newCap); + auto const p = _allocateWrap::realloc(_m, _m.data, newCap); _m.data = p; _m.end = p + oldSize; _m.reservEnd = p + newCap; } else - { T *const newData = _allocateWrap::allocate(_m, newCap); + { auto const newData = _allocateWrap::allocate(_m, newCap); _m.end = _detail::Relocate(_m.data, oldSize, newData); _resetData(newData, newCap); } @@ -437,7 +446,7 @@ class dynarray } _detail::MemcpyCheck(src, count, _m.data); - return src + count; + return src + as_signed(count); } else { auto cpy = [](InputIter src_, T *__restrict dest, T * dLast) @@ -445,14 +454,14 @@ class dynarray while (dest != dLast) { *dest = *src_; - ++src_; ++dest; + ++dest; ++src_; } return src_; }; T * newEnd; if (capacity() < count) { - T *const newData = _allocateChecked(count); + auto const newData = _allocateChecked(count); // Old elements might hold some limited resource, probably good to destroy them before constructing new _detail::Destroy(_m.data, _m.end); _resetData(newData, count); @@ -473,7 +482,7 @@ class dynarray while (_m.end < newEnd) { // each iteration updates _m.end for exception safety _alloTrait::construct(_m, _m.end, *src); - ++src; ++_m.end; + ++_m.end; ++src; } return src; } @@ -515,12 +524,12 @@ class dynarray if constexpr (can_memmove_with) { _detail::MemcpyCheck(src, count, _m.end); - src += count; + src += as_signed(count); _m.end += count; } else { T *__restrict dest = _m.end; - T *const dLast = dest + count; + auto const dLast = dest + count; OEL_TRY_ { while (dest != dLast) @@ -546,8 +555,8 @@ class dynarray { auto const newData = _allocateWrap::allocate(_m, newCap); // Exception free from here - auto const nBefore = pos - _m.data; - auto const nAfter = _m.end - pos; + auto const nBefore = as_unsigned(pos - _m.data); + auto const nAfter = as_unsigned(_m.end - pos); T *const newPos = _detail::Relocate(_m.data, nBefore, newData); _m.end = _detail::Relocate(pos, nAfter, newPos + count); @@ -601,7 +610,7 @@ typename dynarray::iterator _alloTrait::construct(_m, reinterpret_cast(&tmp), static_cast(args)...); if (_m.end < _m.reservEnd) { // Relocate [pos, end) to [pos + 1, end + 1) - size_t const bytesAfterPos{sizeof(T) * (_m.end - pPos)}; + auto const bytesAfterPos = sizeof(T) * as_unsigned(_m.end - pPos); std::memmove( static_cast(pPos + 1), static_cast(pPos), @@ -632,7 +641,7 @@ typename dynarray::iterator static_assert( std::is_same_v, "insert_range requires that source models std::ranges::forward_range or that source.size() is valid" ); - size_t const bytesAfterPos{sizeof(T) * (_m.end - pPos)}; + auto const bytesAfterPos = sizeof(T) * as_unsigned(_m.end - pPos); T * dLast; if (_unusedCapacity() >= count) { @@ -800,7 +809,7 @@ inline void dynarray::append(size_type count, const T &__restrict val) if (_unusedCapacity() < count) _growBy(count); - T *const pos = _m.end; + auto const pos = _m.end; _uninitFill::template call< _detail::ForwardT >(pos, pos + count, _m, val); _debugSizeUpdater guard{_m}; @@ -821,7 +830,7 @@ inline void dynarray::pop_back() noexcept template< typename T, typename Alloc > void dynarray::erase_to_end(iterator first) noexcept { - T *const newEnd = to_pointer_contiguous(first); + T *const newEnd{to_pointer_contiguous(first)}; OEL_ASSERT(_m.data <= newEnd and newEnd <= _m.end); _detail::Destroy(newEnd, _m.end); @@ -856,16 +865,16 @@ typename dynarray::iterator dynarray::erase(iterator pos) _ { _debugSizeUpdater guard{_m}; - T *const ptr = to_pointer_contiguous(pos); + T *const ptr{to_pointer_contiguous(pos)}; OEL_ASSERT(_m.data <= ptr and ptr < _m.end); if constexpr (is_trivially_relocatable::value) { ptr-> ~T(); - T *const next = ptr + 1; + auto const next = ptr + 1; std::memmove( // relocate [pos + 1, end) to [pos, end - 1) static_cast(ptr), static_cast(next), - sizeof(T) * (_m.end - next) ); + sizeof(T) * as_unsigned(_m.end - next) ); --_m.end; } else @@ -880,8 +889,8 @@ typename dynarray::iterator dynarray::erase(iterator first, { _debugSizeUpdater guard{_m}; - T * dest = to_pointer_contiguous(first); - const T *const pLast = to_pointer_contiguous(last); + T * dest{to_pointer_contiguous(first)}; + const T *const pLast{to_pointer_contiguous(last)}; OEL_ASSERT(_m.data <= dest and dest <= pLast and pLast <= _m.end); if constexpr (is_trivially_relocatable::value) @@ -891,7 +900,7 @@ typename dynarray::iterator dynarray::erase(iterator first, std::memmove( // relocate [last, end) to [first, first + nAfter) static_cast(dest), static_cast(pLast), - sizeof(T) * nAfter ); + sizeof(T) * as_unsigned(nAfter) ); _m.end = dest + nAfter; } else if (dest < pLast) // must avoid self-move-assigning the elements @@ -904,16 +913,6 @@ typename dynarray::iterator dynarray::erase(iterator first, } -template< typename T, typename Alloc > -const T & dynarray::at(size_type i) const -{ - if (i < size()) // would be unsafe with signed size_type - return _m.data[i]; - else - _detail::OutOfRange::raise("Bad index dynarray::at"); -} - - template< typename InputRange, typename Alloc = allocator<> > explicit dynarray(InputRange &&, Alloc = {}) -> dynarray< diff --git a/unit_test/CMakeLists.txt b/unit_test/CMakeLists.txt index 76a797c3..c2ec8492 100644 --- a/unit_test/CMakeLists.txt +++ b/unit_test/CMakeLists.txt @@ -47,7 +47,7 @@ else() if(MEM_BOUND_DEBUG) target_compile_options(oel-test PRIVATE -fno-strict-aliasing) endif() - target_compile_options(oel-test PRIVATE -Wall -Wextra -Wold-style-cast -Wshadow -Wconversion -Wno-sign-conversion) + target_compile_options(oel-test PRIVATE -Wall -Wextra -Wold-style-cast -Wshadow -Wconversion -Wsign-conversion) endif() target_link_libraries(oel-test gtest_main) diff --git a/unit_test/dynarray_construct_assignop_swap_gtest.cpp b/unit_test/dynarray_construct_assignop_swap_gtest.cpp index f431fa55..f08cfaad 100644 --- a/unit_test/dynarray_construct_assignop_swap_gtest.cpp +++ b/unit_test/dynarray_construct_assignop_swap_gtest.cpp @@ -282,7 +282,7 @@ TEST_F(dynarrayConstructTest, constructRangeNoCopyAssign) TEST_F(dynarrayConstructTest, constructForwardRangeNoSize) { - for (size_t const n : {0, 1, 59}) + for (auto const n : {0u, 1u, 59u}) { std::forward_list li(n, -6); dynarray d(li); @@ -373,12 +373,12 @@ void testConstructMoveElements() g_allocCount.clear(); T::clearCount(); // not propagating, not equal, cannot steal the memory - for (auto const na : {0, 1, 101}) + for (auto const na : {0u, 1u, 101u}) { using Alloc = StatefulAllocator; dynarray a(reserve, na, Alloc{1}); - for (int i = 0; i < na; ++i) + for (unsigned i{}; i < na; ++i) a.emplace_back(i + 0.5); auto const capBefore = a.capacity(); @@ -398,7 +398,7 @@ void testConstructMoveElements() EXPECT_EQ(capBefore, a.capacity()); ASSERT_EQ(na, ssize(b)); - for (int i = 0; i < na; ++i) + for (unsigned i{}; i < na; ++i) EXPECT_TRUE(b[i].hasValue() and *b[i] == i + 0.5); } EXPECT_EQ(T::nConstructions, T::nDestruct); @@ -471,8 +471,8 @@ void testAssignMoveElements() for (auto const nb : {0, 1, 2}) { using Alloc = StatefulAllocator; - dynarray a(reserve, na, Alloc{1}); - dynarray b(reserve, nb, Alloc{2}); + dynarray a(reserve, as_unsigned(na), Alloc{1}); + dynarray b(reserve, as_unsigned(nb), Alloc{2}); ASSERT_FALSE(a.get_allocator() == b.get_allocator()); @@ -497,7 +497,7 @@ void testAssignMoveElements() EXPECT_EQ(capBefore, a.capacity()); ASSERT_EQ(na, ssize(b)); - for (int i = 0; i < na; ++i) + for (size_t i{}; i < as_unsigned(na); ++i) EXPECT_TRUE(b[i].hasValue() and *b[i] == i + 0.5); } EXPECT_EQ(T::nConstructions, T::nDestruct); diff --git a/unit_test/dynarray_mutate_gtest.cpp b/unit_test/dynarray_mutate_gtest.cpp index fff3ef36..a6441549 100644 --- a/unit_test/dynarray_mutate_gtest.cpp +++ b/unit_test/dynarray_mutate_gtest.cpp @@ -292,7 +292,7 @@ TEST_F(dynarrayTest, assignNonForwardRange) decltype(das) copyDest; copyDest.assign(view::counted(das.cbegin(), 2)); - copyDest.assign( view::counted(begin(das), das.size()) ); + copyDest.assign( view::counted(begin(das), ssize(das)) ); EXPECT_TRUE(das == copyDest); @@ -394,7 +394,7 @@ TEST_F(dynarrayTest, appendNonForwardRange) EXPECT_EQ(it, end); EXPECT_EQ(3u, dest.size()); for (int i = 0; i < 3; ++i) - EXPECT_EQ(i + 1, dest[i]); + EXPECT_EQ( i + 1, dest[oel::as_unsigned(i)] ); } #endif @@ -453,7 +453,7 @@ TEST_F(dynarrayTest, insertR) if (countThrow < toInsert.size()) { #if OEL_HAS_EXCEPTIONS - TrivialRelocat::countToThrowOn = countThrow; + TrivialRelocat::countToThrowOn = oel::as_signed(countThrow); EXPECT_THROW( dest.insert_range(dest.begin() + insertOffset, toInsert), TestException ); #endif EXPECT_TRUE(initSize <= dest.size() and dest.size() <= initSize + countThrow); @@ -500,7 +500,7 @@ TEST_F(dynarrayTest, emplace) { TrivialRelocat::countToThrowOn = -1; g_allocCount.countToThrowOn = -1; - dynarrayTrackingAlloc dest(oel::reserve, nReserve); + dynarrayTrackingAlloc dest(oel::reserve, oel::as_unsigned(nReserve)); dest.emplace(dest.begin(), firstVal); dest.emplace(dest.begin(), secondVal); @@ -519,7 +519,7 @@ TEST_F(dynarrayTest, emplace) { dest.emplace(dest.begin() + insertOffset); EXPECT_EQ(initSize + 1, ssize(dest)); - EXPECT_FALSE( dest.at(insertOffset).hasValue() ); + EXPECT_FALSE( dest.at(oel::as_unsigned(insertOffset)).hasValue() ); } if (insertOffset == 0) { @@ -961,9 +961,9 @@ TEST_F(dynarrayTest, misc) dest0.reserve(1); dest0 = daSrc; - dest0.append( view::counted(daSrc.cbegin(), daSrc.size()) ); + dest0.append( view::counted(daSrc.cbegin(), ssize(daSrc)) ); dest0.append(view::counted(fASrc, 2)); - auto srcEnd = dest0.append( view::counted(begin(dequeSrc), dequeSrc.size()) ); + auto srcEnd = dest0.append( view::counted(begin(dequeSrc), ssize(dequeSrc)) ); EXPECT_TRUE(end(dequeSrc) == srcEnd); dynarray dest1; diff --git a/unit_test/range_algo_gtest.cpp b/unit_test/range_algo_gtest.cpp index a8231fa4..3bfc2047 100644 --- a/unit_test/range_algo_gtest.cpp +++ b/unit_test/range_algo_gtest.cpp @@ -15,14 +15,14 @@ namespace view = oel::view; -TEST(rangeTest, eraseUnstable) +TEST(rangeTest, unorderedErase) { std::deque d{"aa", "bb", "cc"}; - oel::unordered_erase(d, 1); + oel::unordered_erase(d, 1u); EXPECT_EQ(2U, d.size()); EXPECT_EQ("cc", d.back()); - oel::unordered_erase(d, 1); + oel::unordered_erase(d, 1u); EXPECT_EQ(1U, d.size()); EXPECT_EQ("aa", d.front()); } diff --git a/unit_test/util_gtest.cpp b/unit_test/util_gtest.cpp index 98bcdae2..7554e619 100644 --- a/unit_test/util_gtest.cpp +++ b/unit_test/util_gtest.cpp @@ -164,8 +164,8 @@ TEST(utilTest, makeUnique) EXPECT_TRUE(ps[0].empty()); EXPECT_TRUE(ps[1].empty()); - auto a = oel::make_unique_for_overwrite(5); - for (int i = 0; i < 5; ++i) + auto a = oel::make_unique_for_overwrite(5); + for (size_t i{}; i < 5u; ++i) a[i] = i; } diff --git a/unit_test/view_gtest.cpp b/unit_test/view_gtest.cpp index 6b5fe0da..1821f73a 100644 --- a/unit_test/view_gtest.cpp +++ b/unit_test/view_gtest.cpp @@ -80,7 +80,7 @@ TEST(viewTest, viewCounted) #endif { oel::dynarray i{1, 2}; - auto test = view::counted(i.begin(), i.size()); + auto test = view::counted(i.begin(), ssize(i)); EXPECT_EQ(i.size(), test.size()); EXPECT_EQ(1, test[0]); EXPECT_EQ(2, test[1]); @@ -148,7 +148,7 @@ constexpr auto multBy2(StdArrInt2 a) { constexpr auto operator()(int i) const { return 2 * i; } } mult2{}; auto v = view::transform(a, mult2); - std::ptrdiff_t i{}; + size_t i{}; for (auto val : v) res[i++] = val; diff --git a/view/counted.h b/view/counted.h index 0712ab6a..2d2b9a51 100644 --- a/view/counted.h +++ b/view/counted.h @@ -33,8 +33,7 @@ class counted > constexpr Iterator end() const { return _begin + _size; } - constexpr std::make_unsigned_t - size() const noexcept OEL_ALWAYS_INLINE { return _size; } + constexpr auto size() const noexcept OEL_ALWAYS_INLINE { return std::make_unsigned_t(_size); } constexpr bool empty() const noexcept { return 0 == _size; } diff --git a/view/owning.h b/view/owning.h index 0b744db1..725b9085 100644 --- a/view/owning.h +++ b/view/owning.h @@ -37,18 +37,25 @@ class owning constexpr auto end() -> decltype( adl_end(std::declval()) ) { return adl_end(_r); } - template< typename R = Range > OEL_ALWAYS_INLINE - constexpr auto size() - -> decltype(as_unsigned( _detail::Size(std::declval()) )) - { - return _detail::Size(_r); - } + template< typename R = Range, + typename SizeT = decltype(as_unsigned( _detail::Size(std::declval()) )) + > OEL_ALWAYS_INLINE + constexpr SizeT size() { return static_cast(_detail::Size(_r)); } - constexpr bool empty() { return _r.empty(); } + constexpr bool empty() { return _r.empty(); } constexpr decltype(auto) operator[](difference_type index) - OEL_REQUIRES(requires{ _r[index]; }) { return _r[index]; } - + OEL_REQUIRES(requires{ _r[index]; }) + { + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsign-conversion" + #endif + return _r[index]; + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + } constexpr Range base() && { return std::move(_r); } constexpr const Range & base() const & noexcept { return _r; } void base() const && = delete; diff --git a/view/subrange.h b/view/subrange.h index d1e1c1fe..511d1a47 100644 --- a/view/subrange.h +++ b/view/subrange.h @@ -30,10 +30,13 @@ class subrange //! Provided only if begin() can be subtracted from end() template< typename I = Iterator, - enable_if< !disable_sized_sentinel_for > = 0 + enable_if< !disable_sized_sentinel_for > = 0, + typename Ret = decltype( as_unsigned(std::declval() - std::declval()) ) > - constexpr auto size() const - -> decltype( as_unsigned(std::declval() - std::declval()) ) { return _m.second() - _m.first; } + constexpr Ret size() const + { + return static_cast(_m.second() - _m.first); + } constexpr bool empty() const { return _m.first == _m.second(); }