Skip to content

Commit 7dbe01f

Browse files
Add SFINAE tests
1 parent 2ffd408 commit 7dbe01f

File tree

11 files changed

+471
-200
lines changed

11 files changed

+471
-200
lines changed

include/beman/any_view/any_view.hpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#ifndef BEMAN_ANY_VIEW_ANY_VIEW_HPP
44
#define BEMAN_ANY_VIEW_ANY_VIEW_HPP
55

6+
#include <beman/any_view/concepts.hpp>
67
#include <beman/any_view/config.hpp>
78
#include <beman/any_view/detail/iterator.hpp>
89

@@ -25,6 +26,13 @@
2526
#include <ranges>
2627

2728
namespace beman::any_view {
29+
namespace detail {
30+
31+
template <class RangeT, class AnyViewT>
32+
concept viewable_range_compatible_with = not std::same_as<std::remove_cvref_t<RangeT>, AnyViewT> and
33+
ext_viewable_range_compatible_with<RangeT, range_traits<AnyViewT>>;
34+
35+
} // namespace detail
2836

2937
#if BEMAN_ANY_VIEW_USE_FLAGS()
3038

@@ -34,13 +42,12 @@ template <class ElementT,
3442
class RValueRefT = detail::as_rvalue_t<RefT>,
3543
class DiffT = std::ptrdiff_t>
3644
class any_view : public std::ranges::view_interface<any_view<ElementT, OptionsV, RefT, RValueRefT, DiffT>> {
37-
using iterator_concept = detail::iterator_concept_t<OptionsV>;
45+
using iterator_concept = decltype(detail::get_iterator_concept<OptionsV>());
3846
using iterator = detail::iterator<iterator_concept, ElementT, RefT, RValueRefT, DiffT>;
3947
using sentinel = std::default_sentinel_t;
4048
using size_type = std::make_unsigned_t<DiffT>;
4149

42-
static constexpr bool sized = (OptionsV & any_view_options::sized) == any_view_options::sized;
43-
static constexpr bool borrowed = (OptionsV & any_view_options::borrowed) == any_view_options::borrowed;
50+
static constexpr bool sized = (OptionsV & any_view_options::sized) == any_view_options::sized;
4451
static constexpr bool copyable =
4552
#if BEMAN_ANY_VIEW_USE_MOVE_ONLY()
4653
not
@@ -49,6 +56,9 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, OptionsV,
4956
static constexpr bool simple = (OptionsV & any_view_options::simple) == any_view_options::simple;
5057

5158
public:
59+
template <detail::viewable_range_compatible_with<any_view> RangeT>
60+
any_view(RangeT&&);
61+
5262
any_view(const any_view&)
5363
requires(not copyable)
5464
= delete;
@@ -97,8 +107,7 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, RangeTrai
97107
using sentinel = std::default_sentinel_t;
98108
using size_type = std::make_unsigned_t<difference_type>;
99109

100-
static constexpr bool sized = detail::sized_or_v<false, RangeTraitsT>;
101-
static constexpr bool borrowed = detail::borrowed_or_v<false, RangeTraitsT>;
110+
static constexpr bool sized = detail::sized_or_v<false, RangeTraitsT>;
102111
static constexpr bool copyable =
103112
#if BEMAN_ANY_VIEW_USE_MOVE_ONLY()
104113
not
@@ -107,6 +116,9 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, RangeTrai
107116
static constexpr bool simple = detail::simple_or_v<false, RangeTraitsT>;
108117

109118
public:
119+
template <detail::viewable_range_compatible_with<any_view> RangeT>
120+
any_view(RangeT&&);
121+
110122
constexpr any_view(const any_view&)
111123
requires copyable
112124
= default;
@@ -146,8 +158,7 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, OptionsV>
146158
using sentinel = std::default_sentinel_t;
147159
using size_type = std::make_unsigned_t<difference_type>;
148160

149-
static constexpr bool sized = OptionsV.sized;
150-
static constexpr bool borrowed = OptionsV.borrowed;
161+
static constexpr bool sized = OptionsV.sized;
151162
static constexpr bool copyable =
152163
#if BEMAN_ANY_VIEW_USE_MOVE_ONLY()
153164
not
@@ -156,6 +167,9 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, OptionsV>
156167
static constexpr bool simple = OptionsV.simple;
157168

158169
public:
170+
template <detail::viewable_range_compatible_with<any_view> RangeT>
171+
any_view(RangeT&&);
172+
159173
constexpr any_view(const any_view&)
160174
requires copyable
161175
= default;

include/beman/any_view/any_view_options.hpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ namespace beman::any_view {
2222
#if BEMAN_ANY_VIEW_USE_FLAGS()
2323

2424
enum class any_view_options {
25-
input = 0b000000001,
26-
forward = 0b000000011,
27-
bidirectional = 0b000000111,
28-
random_access = 0b000001111,
29-
contiguous = 0b000011111,
30-
sized = 0b000100000,
31-
borrowed = 0b001000000,
32-
BEMAN_ANY_VIEW_OPTION() = 0b010000000,
33-
simple = 0b100000000,
25+
input = 0b00000000,
26+
forward = 0b00000001,
27+
bidirectional = 0b00000011,
28+
random_access = 0b00000111,
29+
contiguous = 0b00001111,
30+
sized = 0b00010000,
31+
borrowed = 0b00100000,
32+
BEMAN_ANY_VIEW_OPTION() = 0b01000000,
33+
simple = 0b10000000,
3434
};
3535

3636
constexpr auto operator|(any_view_options l, any_view_options r) noexcept -> any_view_options {
@@ -71,14 +71,10 @@ consteval auto get_iterator_concept() {
7171
} else if constexpr (iterator_concept == forward) {
7272
return std::forward_iterator_tag{};
7373
} else {
74-
static_assert(iterator_concept == input);
7574
return std::input_iterator_tag{};
7675
}
7776
}
7877

79-
template <any_view_options OptionsV>
80-
using iterator_concept_t = decltype(detail::get_iterator_concept<OptionsV>());
81-
8278
} // namespace detail
8379

8480
#elif BEMAN_ANY_VIEW_USE_NAMED()
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
3+
#ifndef BEMAN_ANY_VIEW_CONCEPTS_HPP
4+
#define BEMAN_ANY_VIEW_CONCEPTS_HPP
5+
6+
#include <beman/any_view/range_traits.hpp>
7+
#include <iterator>
8+
9+
namespace beman::any_view {
10+
namespace detail {
11+
12+
template <class IterT, class IterConceptT>
13+
concept input_iterator_compatible_with =
14+
std::input_or_output_iterator<IterT> and
15+
(not std::derived_from<IterConceptT, std::input_iterator_tag> or std::input_iterator<IterT>);
16+
17+
template <class IterT, class IterConceptT>
18+
concept forward_iterator_compatible_with =
19+
input_iterator_compatible_with<IterT, IterConceptT> and
20+
(not std::derived_from<IterConceptT, std::forward_iterator_tag> or std::forward_iterator<IterT>);
21+
22+
template <class IterT, class IterConceptT>
23+
concept bidirectional_iterator_compatible_with =
24+
forward_iterator_compatible_with<IterT, IterConceptT> and
25+
(not std::derived_from<IterConceptT, std::bidirectional_iterator_tag> or std::bidirectional_iterator<IterT>);
26+
27+
template <class IterT, class IterConceptT>
28+
concept random_access_iterator_compatible_with =
29+
bidirectional_iterator_compatible_with<IterT, IterConceptT> and
30+
(not std::derived_from<IterConceptT, std::random_access_iterator_tag> or std::random_access_iterator<IterT>);
31+
32+
template <class IterT, class IterConceptT>
33+
concept contiguous_iterator_compatible_with =
34+
random_access_iterator_compatible_with<IterT, IterConceptT> and
35+
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or std::contiguous_iterator<IterT>);
36+
37+
template <class RangeRefT, class TraitsRefT, class IterConceptT>
38+
concept contiguous_reference_convertible_to =
39+
std::convertible_to<RangeRefT, TraitsRefT> and
40+
(not std::derived_from<IterConceptT, std::contiguous_iterator_tag> or
41+
std::convertible_to<std::remove_reference_t<RangeRefT> (*)[], std::remove_reference_t<TraitsRefT> (*)[]>);
42+
43+
template <class RangeT, class RangeTraitsT>
44+
concept sized_range_compatible_with = not RangeTraitsT::sized or std::ranges::sized_range<RangeT>;
45+
46+
template <class RangeT, class RangeTraitsT>
47+
concept borrowed_range_compatible_with = not RangeTraitsT::borrowed or std::ranges::borrowed_range<RangeT>;
48+
49+
template <class RangeT, class RangeTraitsT>
50+
concept range_compatible_with =
51+
std::ranges::range<RangeT> and
52+
contiguous_iterator_compatible_with<std::ranges::iterator_t<RangeT>, iterator_concept_t<RangeTraitsT>> and
53+
contiguous_reference_convertible_to<std::ranges::range_reference_t<RangeT>,
54+
reference_type_t<RangeTraitsT>,
55+
iterator_concept_t<RangeTraitsT>> and
56+
std::convertible_to<std::ranges::range_rvalue_reference_t<RangeT>, rvalue_reference_type_t<RangeTraitsT>> and
57+
std::convertible_to<std::ranges::range_difference_t<RangeT>, difference_type_t<RangeTraitsT>> and
58+
sized_range_compatible_with<RangeT, RangeTraitsT> and borrowed_range_compatible_with<RangeT, RangeTraitsT>;
59+
60+
template <class ViewT, class RangeTraitsT>
61+
concept copyable_view_compatible_with =
62+
#if BEMAN_ANY_VIEW_USE_COPYABLE()
63+
not
64+
#endif
65+
RangeTraitsT::BEMAN_ANY_VIEW_OPTION() or
66+
std::copyable<ViewT>;
67+
68+
template <bool SimpleV, class ViewT>
69+
using const_if_t = std::conditional_t<SimpleV, const ViewT, ViewT>;
70+
71+
template <class ViewT, class RangeTraitsT>
72+
concept view_compatible_with = copyable_view_compatible_with<ViewT, RangeTraitsT> and
73+
range_compatible_with<const_if_t<RangeTraitsT::simple, ViewT>, RangeTraitsT>;
74+
75+
} // namespace detail
76+
77+
template <class RangeT, class RangeTraitsT>
78+
concept ext_viewable_range_compatible_with =
79+
std::ranges::viewable_range<RangeT> and detail::view_compatible_with<std::views::all_t<RangeT>, RangeTraitsT>;
80+
81+
} // namespace beman::any_view
82+
83+
#endif // BEMAN_ANY_VIEW_CONCEPTS_HPP

include/beman/any_view/detail/concepts.hpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ concept simple_range = std::ranges::range<RangeT> and std::ranges::range<const R
1414
std::same_as<std::ranges::iterator_t<RangeT>, std::ranges::iterator_t<const RangeT>> and
1515
std::same_as<std::ranges::sentinel_t<RangeT>, std::ranges::sentinel_t<const RangeT>>;
1616

17-
template <class ViewT>
18-
concept BEMAN_ANY_VIEW_OPTION_(range) =
19-
#if BEMAN_ANY_VIEW_USE_MOVE_ONLY()
20-
not
21-
#endif
22-
std::copyable<ViewT> and
23-
std::ranges::range<ViewT>;
24-
2517
} // namespace beman::any_view::detail
2618

2719
#endif // BEMAN_ANY_VIEW_DETAIL_CONCEPTS_HPP

include/beman/any_view/detail/iterator.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ namespace beman::any_view::detail {
1313

1414
template <class IterConceptT, class ElementT, class RefT, class RValueRefT, class DiffT>
1515
class iterator {
16-
using reference = RefT;
17-
using pointer = std::add_pointer_t<RefT>;
16+
using reference = RefT;
17+
using rvalue_reference = RValueRefT;
18+
using pointer = std::add_pointer_t<RefT>;
1819

1920
public:
2021
using iterator_concept = IterConceptT;
@@ -23,6 +24,8 @@ class iterator {
2324

2425
auto operator*() const -> reference;
2526

27+
friend auto iter_move(const iterator&) -> rvalue_reference;
28+
2629
auto operator->() const -> pointer;
2730

2831
auto operator++() -> iterator&;
@@ -54,9 +57,6 @@ class iterator {
5457
auto operator==(std::default_sentinel_t) const -> bool;
5558
};
5659

57-
template <class IterConceptT, class ElementT, class RefT, class RValueRefT, class DiffT>
58-
auto iter_move(const iterator<IterConceptT, ElementT, RefT, RValueRefT, DiffT>&) -> RValueRefT;
59-
6060
} // namespace beman::any_view::detail
6161

6262
#endif // BEMAN_ANY_VIEW_DETAIL_ITERATOR_HPP

include/beman/any_view/range_traits.hpp

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,14 @@
44
#define BEMAN_ANY_VIEW_RANGE_TRAITS_HPP
55

66
#include <beman/any_view/config.hpp>
7-
8-
#if BEMAN_ANY_VIEW_USE_TRAITS()
9-
107
#include <beman/any_view/detail/concepts.hpp>
118

129
#include <ranges>
1310

14-
#endif
15-
1611
namespace beman::any_view {
17-
18-
#if BEMAN_ANY_VIEW_USE_TRAITS()
19-
2012
namespace detail {
2113

22-
template <std::ranges::input_range RangeT>
14+
template <std::ranges::range RangeT>
2315
consteval auto get_range_concept() {
2416
if constexpr (std::ranges::contiguous_range<RangeT>) {
2517
return std::contiguous_iterator_tag{};
@@ -30,12 +22,11 @@ consteval auto get_range_concept() {
3022
} else if constexpr (std::ranges::forward_range<RangeT>) {
3123
return std::forward_iterator_tag{};
3224
} else {
33-
static_assert(std::ranges::input_range<RangeT>);
3425
return std::input_iterator_tag{};
3526
}
3627
}
3728

38-
template <std::ranges::range RangeT>
29+
template <class RangeT>
3930
using range_concept_t = decltype(detail::get_range_concept<RangeT>());
4031

4132
template <class DefaultT, template <class...> class OpT, class... ArgsT>
@@ -88,14 +79,16 @@ struct range_traits {
8879
using rvalue_reference_type = std::ranges::range_rvalue_reference_t<RangeT>;
8980
using difference_type = std::ranges::range_difference_t<RangeT>;
9081

91-
static constexpr bool sized = std::ranges::sized_range<RangeT>;
92-
static constexpr bool borrowed = std::ranges::enable_borrowed_range<RangeT>;
93-
static constexpr bool BEMAN_ANY_VIEW_OPTION() = detail::BEMAN_ANY_VIEW_OPTION_(range)<RangeT>;
94-
static constexpr bool simple = detail::simple_range<RangeT>;
82+
static constexpr bool sized = std::ranges::sized_range<RangeT>;
83+
static constexpr bool borrowed = std::ranges::borrowed_range<RangeT>;
84+
static constexpr bool BEMAN_ANY_VIEW_OPTION() =
85+
#if BEMAN_ANY_VIEW_USE_MOVE_ONLY()
86+
not
87+
#endif
88+
std::copyable<RangeT>;
89+
static constexpr bool simple = detail::simple_range<RangeT>;
9590
};
9691

97-
#endif // BEMAN_ANY_VIEW_USE_TRAITS()
98-
9992
} // namespace beman::any_view
10093

10194
#endif // BEMAN_ANY_VIEW_RANGE_TRAITS_HPP

tests/beman/any_view/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ function(beman_add_test)
1010
endfunction()
1111

1212
beman_add_test(TARGET concepts SOURCES concepts.test.cpp)
13+
beman_add_test(TARGET sfinae SOURCES sfinae.test.cpp)
1314
beman_add_test(TARGET type_traits SOURCES type_traits.test.cpp)

0 commit comments

Comments
 (0)