1 /// \file
2 // Range v3 library
3 //
4 //  Copyright Eric Niebler 2013-present
5 //
6 //  Use, modification and distribution is subject to the
7 //  Boost Software License, Version 1.0. (See accompanying
8 //  file LICENSE_1_0.txt or copy at
9 //  http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 
14 #ifndef RANGES_V3_VIEW_SINGLE_HPP
15 #define RANGES_V3_VIEW_SINGLE_HPP
16 
17 #include <type_traits>
18 #include <utility>
19 
20 #include <range/v3/range_fwd.hpp>
21 
22 #include <range/v3/iterator/concepts.hpp>
23 #include <range/v3/iterator/traits.hpp>
24 #include <range/v3/range/access.hpp>
25 #include <range/v3/range/concepts.hpp>
26 #include <range/v3/range/traits.hpp>
27 #include <range/v3/utility/addressof.hpp>
28 #include <range/v3/utility/optional.hpp>
29 #include <range/v3/utility/semiregular_box.hpp>
30 #include <range/v3/utility/static_const.hpp>
31 #include <range/v3/view/facade.hpp>
32 
33 #include <range/v3/detail/prologue.hpp>
34 
35 namespace ranges
36 {
37     /// \addtogroup group-views
38     /// @{
39     template<typename T>
40     struct single_view : view_interface<single_view<T>, (cardinality)1>
41     {
42     private:
43         CPP_assert(copy_constructible<T>);
44         static_assert(std::is_object<T>::value,
45                       "The template parameter of single_view must be an object type");
46         semiregular_box_t<T> value_;
47         template<typename... Args>
single_viewranges::single_view48         constexpr single_view(in_place_t, std::true_type, Args &&... args)
49           : value_{static_cast<Args &&>(args)...}
50         {}
51         template<typename... Args>
single_viewranges::single_view52         constexpr single_view(in_place_t, std::false_type, Args &&... args)
53           : value_{in_place, static_cast<Args &&>(args)...}
54         {}
55 
56     public:
57         single_view() = default;
single_viewranges::single_view58         constexpr explicit single_view(T const & t)
59           : value_(t)
60         {}
single_viewranges::single_view61         constexpr explicit single_view(T && t)
62           : value_(std::move(t))
63         {}
64         template(class... Args)(
65             /// \pre
66             requires constructible_from<T, Args...>)
67             constexpr single_view(in_place_t, Args &&... args)
68           : single_view{in_place,
69                         meta::bool_<(bool)semiregular<T>>{},
70                         static_cast<Args &&>(args)...}
71         {}
72         constexpr T * begin() noexcept
73         {
74             return data();
75         }
76         constexpr T const * begin() const noexcept
77         {
78             return data();
79         }
80         constexpr T * end() noexcept
81         {
82             return data() + 1;
83         }
84         constexpr T const * end() const noexcept
85         {
86             return data() + 1;
87         }
88         static constexpr std::size_t size() noexcept
89         {
90             return 1u;
91         }
92         constexpr T * data() noexcept
93         {
94             return detail::addressof(static_cast<T &>(value_));
95         }
96         constexpr T const * data() const noexcept
97         {
98             return detail::addressof(static_cast<T const &>(value_));
99         }
100     };
101 
102 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
103     template<class T>
104     explicit single_view(T &&) //
105         -> single_view<detail::decay_t<T>>;
106 #endif
107 
108     namespace views
109     {
110         struct single_fn
111         {
112             template(typename Val)(
113                 /// \pre
114                 requires copy_constructible<Val>)
115             single_view<Val> operator()(Val value) const
116             {
117                 return single_view<Val>{std::move(value)};
118             }
119         };
120 
121         /// \relates single_fn
122         /// \ingroup group-views
123         RANGES_INLINE_VARIABLE(single_fn, single)
124     } // namespace views
125 
126     namespace cpp20
127     {
128         namespace views
129         {
130             using ranges::views::single;
131         }
132         template(typename T)(
133             /// \pre
134             requires std::is_object<T>::value) //
135             using single_view = ranges::single_view<T>;
136     } // namespace cpp20
137     /// @}
138 } // namespace ranges
139 
140 #include <range/v3/detail/epilogue.hpp>
141 #include <range/v3/detail/satisfy_boost_range.hpp>
142 RANGES_SATISFY_BOOST_RANGE(::ranges::single_view)
143 
144 #endif
145