Skip to content

Commit cdb409a

Browse files
Add default constructor, update moved-from state
1 parent cde5f46 commit cdb409a

File tree

5 files changed

+121
-3
lines changed

5 files changed

+121
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
99
![Lint Check (pre-commit)](https://github.com/bemanproject/any_view/actions/workflows/pre-commit.yml/badge.svg)
1010
![Standard Target](https://github.com/bemanproject/beman/blob/main/images/badges/cpp29.svg)
1111

12-
**Implements**: `std::ranges::any_view` proposed in [any_view (P3411R2)](https://wg21.link/p3411r2).
12+
**Implements**: `std::ranges::any_view` proposed in [any_view (P3411)](https://wg21.link/p3411).
1313

1414
**Status**: [Under development and not yet ready for production use.](https://github.com/bemanproject/beman/blob/main/docs/BEMAN_LIBRARY_MATURITY_MODEL.md#under-development-and-not-yet-ready-for-production-use)
1515

include/beman/any_view/any_view.hpp

Lines changed: 10 additions & 2 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/detail/default_view.hpp>
67
#include <beman/any_view/detail/view_adaptor.hpp>
78

89
namespace beman::any_view {
@@ -38,17 +39,24 @@ class any_view : public std::ranges::view_interface<any_view<ElementT, OptsV, Re
3839
constexpr any_view(RangeT&& range)
3940
: view_ptr(get_in_place_adaptor_type<RangeT>(), std::views::all(std::forward<RangeT>(range))) {}
4041

42+
constexpr any_view() noexcept : any_view(detail::default_view<ElementT, RefT, RValueRefT, DiffT>{}) {}
43+
4144
constexpr any_view(const any_view&)
4245
requires(bool(OptsV& any_view_options::copyable))
4346
= default;
4447

45-
constexpr any_view(any_view&&) noexcept = default;
48+
constexpr any_view(any_view&& other) noexcept : any_view() { swap(other); }
4649

4750
constexpr any_view& operator=(const any_view&)
4851
requires(bool(OptsV& any_view_options::copyable))
4952
= default;
5053

51-
constexpr any_view& operator=(any_view&&) noexcept = default;
54+
constexpr any_view& operator=(any_view&& other) noexcept {
55+
view_ptr = {get_in_place_adaptor_type<detail::default_view<ElementT, RefT, RValueRefT, DiffT>>(),
56+
detail::default_view<ElementT, RefT, RValueRefT, DiffT>{}};
57+
swap(other);
58+
return *this;
59+
}
5260

5361
constexpr ~any_view() = default;
5462

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
3+
#ifndef BEMAN_ANY_VIEW_DETAIL_DEFAULT_VIEW_HPP
4+
#define BEMAN_ANY_VIEW_DETAIL_DEFAULT_VIEW_HPP
5+
6+
#include <beman/any_view/detail/unreachable_iterator.hpp>
7+
8+
#include <ranges>
9+
10+
namespace beman::any_view::detail {
11+
12+
template <class ElementT, class RefT, class RValueRefT, class DiffT>
13+
class default_view : public std::ranges::subrange<unreachable_iterator<ElementT, RefT, RValueRefT, DiffT>> {
14+
public:
15+
using std::ranges::subrange<unreachable_iterator<ElementT, RefT, RValueRefT, DiffT>>::subrange;
16+
using std::ranges::subrange<unreachable_iterator<ElementT, RefT, RValueRefT, DiffT>>::operator=;
17+
};
18+
19+
} // namespace beman::any_view::detail
20+
21+
#endif // BEMAN_ANY_VIEW_DETAIL_DEFAULT_VIEW_HPP
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
3+
#ifndef BEMAN_ANY_VIEW_DETAIL_UNREACHABLE_ITERATOR_HPP
4+
#define BEMAN_ANY_VIEW_DETAIL_UNREACHABLE_ITERATOR_HPP
5+
6+
#include <beman/any_view/detail/utility.hpp>
7+
8+
#include <compare>
9+
#include <iterator>
10+
11+
namespace beman::any_view::detail {
12+
13+
template <class ElementT, class RefT, class RValueRefT, class DiffT>
14+
struct iterator_concept {
15+
using type = std::random_access_iterator_tag;
16+
};
17+
18+
template <class ElementT>
19+
struct iterator_concept<ElementT, ElementT&, ElementT&&, std::ptrdiff_t> {
20+
using type = std::contiguous_iterator_tag;
21+
};
22+
23+
template <class ElementT, class RefT, class RValueRefT, class DiffT>
24+
class unreachable_iterator {
25+
public:
26+
using iterator_concept = iterator_concept<ElementT, RefT, RValueRefT, DiffT>::type;
27+
using element_type = ElementT;
28+
using difference_type = DiffT;
29+
30+
constexpr auto operator*() const noexcept -> RefT { unreachable(); }
31+
32+
constexpr friend auto iter_move(unreachable_iterator) noexcept -> RValueRefT { unreachable(); }
33+
34+
constexpr auto operator++() noexcept -> unreachable_iterator& { return *this; }
35+
36+
constexpr auto operator++(int) noexcept -> unreachable_iterator { return *this; }
37+
38+
constexpr auto operator<=>(const unreachable_iterator&) const noexcept -> std::strong_ordering = default;
39+
40+
constexpr auto operator--() noexcept -> unreachable_iterator& { return *this; }
41+
42+
constexpr auto operator--(int) noexcept -> unreachable_iterator { return *this; }
43+
44+
constexpr auto operator-(unreachable_iterator) const noexcept -> difference_type { return 0; }
45+
46+
constexpr auto operator+=(difference_type) noexcept -> unreachable_iterator& { return *this; }
47+
48+
constexpr auto operator+(difference_type) const noexcept -> unreachable_iterator { return *this; }
49+
50+
constexpr friend auto operator+(difference_type, unreachable_iterator) noexcept -> unreachable_iterator {
51+
return {};
52+
}
53+
54+
constexpr auto operator-=(difference_type) noexcept -> unreachable_iterator& { return *this; }
55+
56+
constexpr auto operator-(difference_type) const noexcept -> unreachable_iterator { return *this; }
57+
58+
constexpr auto operator[](difference_type) const noexcept -> RefT { unreachable(); }
59+
60+
constexpr auto operator->() const noexcept -> element_type*
61+
requires std::derived_from<iterator_concept, std::contiguous_iterator_tag>
62+
{
63+
return nullptr;
64+
}
65+
};
66+
67+
} // namespace beman::any_view::detail
68+
69+
#endif // BEMAN_ANY_VIEW_DETAIL_UNREACHABLE_ITERATOR_HPP

tests/beman/any_view/constexpr.test.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,23 @@ TEST(ConstexprTest, reference_lifetime) {
8484
#endif
8585
EXPECT_TRUE(set_front(std::vector{7}, 42));
8686
}
87+
88+
constexpr auto is_empty(any_view<int, forward> view) { return view.empty(); }
89+
90+
TEST(ConstexprTest, default_construct) {
91+
static_assert(is_empty({}));
92+
93+
EXPECT_TRUE(is_empty({}));
94+
}
95+
96+
TEST(ConstexprTest, moved_from) {
97+
const auto make_moved_from = [] {
98+
any_view<int, forward> view = std::vector<int>{42};
99+
auto other = std::move(view);
100+
return view;
101+
};
102+
103+
static_assert(is_empty(make_moved_from()));
104+
105+
EXPECT_TRUE(is_empty(make_moved_from()));
106+
}

0 commit comments

Comments
 (0)