Skip to content

Commit

Permalink
Fixed view-related compile errors
Browse files Browse the repository at this point in the history
Also CMAKE_CXX_STANDARD in workflow yml
  • Loading branch information
OleErikPeistorpet committed Sep 29, 2023
1 parent a75e32c commit 3e71a14
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 46 deletions.
30 changes: 27 additions & 3 deletions .github/workflows/cmake-multi-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,40 @@ jobs:
runs-on: ${{ matrix.os }}

strategy:
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
fail-fast: false
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations.
fail-fast: true

matrix:
os: [ubuntu-20.04, ubuntu-latest, macos-latest]
mem_bound_debug: [off, on]
cpp_standard: [17, 20]
mem_bound_debug: [off]
include:
- os: ubuntu-20.04
gcc_version: 7
cpp_standard: 17
- os: ubuntu-20.04
gcc_version: 8
cpp_standard: 14
mem_bound_debug: on
- os: ubuntu-20.04
gcc_version: 9
cpp_standard: 20
- os: ubuntu-latest
gcc_version: 10
cpp_standard: 20
mem_bound_debug: on
- os: ubuntu-latest
gcc_version: 11
cpp_standard: 17
- os: ubuntu-latest
gcc_version: 12
cpp_standard: 20
- os: macos-latest
cpp_standard: 14
mem_bound_debug: on
exclude:
- os: macos-latest
cpp_standard: 17

steps:
- if: runner.os == 'Linux'
Expand All @@ -39,6 +62,7 @@ jobs:
run: >
cmake -B ${{ github.workspace }}/build
-D CMAKE_BUILD_TYPE=Release
-D CMAKE_CXX_STANDARD=${{ matrix.cpp_standard }}
-D MEM_BOUND_DEBUG=${{ matrix.mem_bound_debug }}
-S ${{ github.workspace }}/unit_test
Expand Down
2 changes: 2 additions & 0 deletions unit_test/dynarray_other_gtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ namespace
#if __cpp_lib_concepts >= 201907
static_assert(std::contiguous_iterator<Iter>);
static_assert(std::contiguous_iterator<ConstIter>);
static_assert(std::sized_sentinel_for<ConstIter, Iter>);
static_assert(std::sized_sentinel_for<Iter, ConstIter>);
#endif

static_assert(std::is_same<std::iterator_traits<ConstIter>::value_type, float>(), "?");
Expand Down
5 changes: 0 additions & 5 deletions unit_test/incl_view_counted.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
#include <view/counted.h>

constexpr auto v()
{
return oel::view::counted((int *)nullptr, 0);
}
2 changes: 1 addition & 1 deletion unit_test/test_classes.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class MemoryLeakDetector;
extern MemoryLeakDetector* leakDetector;


#if __cpp_lib_ranges >= 201911
#if (defined _MSC_VER and __cpp_lib_ranges >= 201911) or __cpp_lib_ranges > 202000

#include <ranges>

Expand Down
34 changes: 20 additions & 14 deletions unit_test/view_gtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ constexpr auto transformIterFromIntPtr(const int * p)
return oel::transform_iterator<F, const int *>{F{}, p};
}

template< typename S >
constexpr oel::sentinel_wrapper<S> makeSentinel(S se) { return {se}; }

TEST(viewTest, basicView)
{
using BV = oel::basic_view<int *>;
Expand All @@ -38,7 +41,7 @@ TEST(viewTest, basicView)
EXPECT_EQ(2, ssize(v));
}
constexpr auto it = transformIterFromIntPtr(src);
constexpr auto v = view::subrange(it, src + 3);
constexpr auto v = view::subrange(it, makeSentinel(src + 3));
EXPECT_EQ(3, ssize(v));
}

Expand Down Expand Up @@ -70,18 +73,21 @@ TEST(viewTest, viewTransformBasics)
{
using Elem = double;

struct MoveOnly
struct MoveOnlyF
{ std::unique_ptr<double> p;
auto operator()(Elem &) const { return 0; }
};
Elem r[1];
auto v = view::transform(r, [](Elem &) { return 0; });
auto v2 = view::transform(r, MoveOnlyF{});
auto itMoveOnly = v2.begin();

using IEmptyLambda = decltype(v.begin());
using IMoveOnly = oel::transform_iterator<MoveOnly, Elem *>;
using IMoveOnly = decltype(itMoveOnly);

static_assert(std::is_same< IEmptyLambda::iterator_category, std::forward_iterator_tag >(), "?");
static_assert(std::is_same< IMoveOnly::iterator_category, std::input_iterator_tag >(), "?");
static_assert(std::is_same< decltype(itMoveOnly++), void >(), "?");
static_assert(sizeof(IEmptyLambda) == sizeof(Elem *), "Not critical, this assert can be removed");
#if OEL_STD_RANGES
static_assert(std::ranges::forward_range<decltype(v)>);
Expand All @@ -96,17 +102,17 @@ TEST(viewTest, viewTransformBasics)
EXPECT_TRUE( it++ == v.begin() );
EXPECT_TRUE( it != v.begin() );
}
EXPECT_TRUE( v.begin() == v.begin().base() );
EXPECT_FALSE( r + 1 == v.begin() );
EXPECT_FALSE( v.begin() != r + 0 );
EXPECT_TRUE( r + 1 != v.begin() );
EXPECT_TRUE( v.begin() == makeSentinel(v.begin().base()) );
EXPECT_FALSE( makeSentinel(r + 1) == v.begin() );
EXPECT_FALSE( v.begin() != makeSentinel(r + 0) );
EXPECT_TRUE( makeSentinel(r + 1) != v.begin() );

auto nested = view::transform(v, [](double d) { return d; });
auto const it = nested.begin();
EXPECT_TRUE(r + 0 == it);
EXPECT_TRUE(r + 1 != it);
EXPECT_FALSE(it == r + 1);
EXPECT_FALSE(it != r + 0);
EXPECT_TRUE(makeSentinel(r + 0) == it.base());
EXPECT_TRUE(makeSentinel(r + 1) != it.base());
EXPECT_FALSE(it.base() == makeSentinel(r + 1));
EXPECT_FALSE(it.base() != makeSentinel(r + 0));
}

#if __cplusplus > 201500 or _HAS_CXX17
Expand All @@ -118,7 +124,7 @@ constexpr auto multBy2(StdArrInt2 a)
StdArrInt2 res{};
struct
{ constexpr auto operator()(int i) const { return 2 * i; }
} mult2;
} mult2{};
auto v = view::transform(a, mult2);
std::ptrdiff_t i{};
for (auto val : v)
Expand Down Expand Up @@ -225,10 +231,10 @@ TEST(viewTest, viewMoveEndDifferentType)
auto nonEmpty = [i = -1](int j) { return i + j; };
int src[1];
oel::transform_iterator<decltype(nonEmpty), int *> it{nonEmpty, src + 0};
auto v = view::move(view::subrange(it, src + 1));
auto v = view::move(view::subrange( it, makeSentinel(src + 1) ));

EXPECT_NE(v.begin(), v.end());
EXPECT_EQ(src + 1, v.end().base());
EXPECT_EQ(src + 1, v.end().base()._s);
}

#if OEL_STD_RANGES
Expand Down
4 changes: 2 additions & 2 deletions view/counted.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ class counted_view

constexpr bool empty() const noexcept { return 0 == _size; }

constexpr decltype(auto) operator[](difference_type index) const OEL_ALWAYS_INLINE
OEL_REQUIRES(iter_is_random_access<Iterator>) { return _begin[index]; }
constexpr decltype(auto) operator[](difference_type index) const
OEL_REQUIRES(iter_is_random_access<Iterator>) OEL_ALWAYS_INLINE { return _begin[index]; }

protected:
Iterator _begin;
Expand Down
17 changes: 17 additions & 0 deletions view/detail/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@

namespace oel
{

template< typename Sentinel >
struct sentinel_wrapper { Sentinel _s; };



namespace _detail
{
template< typename T,
Expand Down Expand Up @@ -89,3 +95,14 @@ namespace _detail
}

} // oel


#if !OEL_STD_RANGES
namespace std
{
// Small hack to let std::move_iterator< sentinel_wrapper<S> > compile
template< typename S >
struct iterator_traits< oel::sentinel_wrapper<S> > : iterator_traits<S> {};

}
#endif
2 changes: 1 addition & 1 deletion view/move.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace _detail
using S = std::conditional_t<
std::is_same_v< iterator_t<V>, sentinel_t<V> >,
_iter,
std::move_sentinel< sentinel_t<V> > // What is it good for?
std::move_sentinel< sentinel_t<V> >
>;
#else
using S = std::move_iterator< sentinel_t<V> >;
Expand Down
4 changes: 2 additions & 2 deletions view/subrange.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class basic_view

constexpr bool empty() const { return _begin == _end; }

constexpr decltype(auto) operator[](difference_type index) const OEL_ALWAYS_INLINE
OEL_REQUIRES(iter_is_random_access<Iterator>) { return _begin[index]; }
constexpr decltype(auto) operator[](difference_type index) const
OEL_REQUIRES(iter_is_random_access<Iterator>) OEL_ALWAYS_INLINE { return _begin[index]; }

protected:
Iterator _begin;
Expand Down
4 changes: 2 additions & 2 deletions view/transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ namespace _detail
}

template< typename Sentinel, typename... None >
constexpr Sentinel _makeSent(Sentinel last, None...)
constexpr sentinel_wrapper<Sentinel> _makeSent(Sentinel last, None...)
{
return last;
return {last};
}

public:
Expand Down
49 changes: 33 additions & 16 deletions view/transform_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,26 +76,43 @@ class transform_iterator

template< typename S >
OEL_REQUIRES(std::sized_sentinel_for<S, Iterator>)
friend constexpr difference_type operator -(const transform_iterator & left, S right) { return left._m.first - right; }
friend constexpr difference_type operator -
(sentinel_wrapper<S> left, const transform_iterator & right) { return left._s - right._m.first; }

template< typename S >
OEL_REQUIRES(std::sized_sentinel_for<S, Iterator>)
friend constexpr difference_type operator -(S left, const transform_iterator & right) { return left - right._m.first; }

constexpr bool operator==(const transform_iterator & right) const { return _m.first == right._m.first; }
constexpr bool operator!=(const transform_iterator & right) const { return _m.first != right._m.first; }
template< typename Sentinel >
friend constexpr bool operator==(const transform_iterator & left, Sentinel right) { return left._m.first == right; }
template< typename Sentinel >
friend constexpr bool operator==(Sentinel left, const transform_iterator & right) { return right._m.first == left; }
template< typename Sentinel >
friend constexpr bool operator!=(const transform_iterator & left, Sentinel right) { return left._m.first != right; }
template< typename Sentinel >
friend constexpr bool operator!=(Sentinel left, const transform_iterator & right) { return right._m.first != left; }
friend constexpr difference_type operator -
(const transform_iterator & left, sentinel_wrapper<S> right) { return left._m.first - right._s; }

constexpr bool operator==(const transform_iterator & right) const { return _m.first == right._m.first; }

constexpr bool operator!=(const transform_iterator & right) const { return _m.first != right._m.first; }

template< typename S >
friend constexpr bool operator==
(const transform_iterator & left, sentinel_wrapper<S> right) { return left._m.first == right._s; }

template< typename S >
friend constexpr bool operator==
(sentinel_wrapper<S> left, const transform_iterator & right) { return right._m.first == left._s; }

template< typename S >
friend constexpr bool operator!=
(const transform_iterator & left, sentinel_wrapper<S> right) { return left._m.first != right._s; }

template< typename S >
friend constexpr bool operator!=
(sentinel_wrapper<S> left, const transform_iterator & right) { return right._m.first != left._s; }
};

template< typename F, typename I >
constexpr bool disable_sized_sentinel_for< transform_iterator<F, I>, transform_iterator<F, I> >
= !iter_is_random_access<I>;
#if __cpp_lib_concepts < 201907
template< typename F, typename I >
constexpr bool disable_sized_sentinel_for< transform_iterator<F, I>, transform_iterator<F, I> >
= disable_sized_sentinel_for<I, I>;

template< typename S, typename F, typename I >
constexpr bool disable_sized_sentinel_for< sentinel_wrapper<S>, transform_iterator<F, I> >
= disable_sized_sentinel_for<S, I>;
#endif

} // namespace oel

0 comments on commit 3e71a14

Please sign in to comment.