File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/XS/librangeV3.x/i/range/v3/utility/box.hpp
Criterion Covered Total %
statement 11 11 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 11 11 100.0


line stmt bran cond sub pod time code
1             /// \file
2             // Range v3 library
3             //
4             // Copyright Eric Niebler 2013-present
5             // Copyright Casey Carter 2016
6             //
7             // Use, modification and distribution is subject to the
8             // Boost Software License, Version 1.0. (See accompanying
9             // file LICENSE_1_0.txt or copy at
10             // http://www.boost.org/LICENSE_1_0.txt)
11             //
12             // Project home: https://github.com/ericniebler/range-v3
13             //
14              
15             #ifndef RANGES_V3_UTILITY_BOX_HPP
16             #define RANGES_V3_UTILITY_BOX_HPP
17              
18             #include
19             #include
20             #include
21             #include
22             #include
23             #include
24             #include
25              
26             namespace ranges
27             {
28             inline namespace v3
29             {
30             /// \addtogroup group-utility Utility
31             /// @{
32             ///
33             template
34             struct mutable_
35             {
36             mutable T value;
37             CONCEPT_REQUIRES(std::is_default_constructible::value)
38             constexpr mutable_()
39             : value{}
40             {}
41             constexpr explicit mutable_(T const &t)
42             : value(t)
43             {}
44             constexpr explicit mutable_(T &&t)
45             : value(detail::move(t))
46             {}
47             mutable_ const &operator=(T const &t) const
48             {
49             value = t;
50             return *this;
51             }
52             mutable_ const &operator=(T &&t) const
53             {
54             value = detail::move(t);
55             return *this;
56             }
57             constexpr operator T &() const &
58             {
59             return value;
60             }
61             };
62              
63             template
64             struct constant
65             {
66             constant() = default;
67             constexpr explicit constant(T const &)
68             {}
69             constant &operator=(T const &)
70             {
71             return *this;
72             }
73             constant const &operator=(T const &) const
74             {
75             return *this;
76             }
77             constexpr operator T() const
78             {
79             return v;
80             }
81             constexpr T exchange(T const &) const
82             {
83             return v;
84             }
85             };
86              
87             static_assert(std::is_trivial>::value, "Expected constant to be trivial");
88              
89             /// \cond
90             namespace detail
91             {
92             // "box" has three different implementations that store a T differently:
93             enum class box_compress {
94             none, // Nothing special: get() returns a reference to a T member subobject
95             ebo, // Apply Empty Base Optimization: get() returns a reference to a T base subobject
96             coalesce // Coalesce all Ts into one T: get() returns a reference to a static T singleton
97             };
98              
99             // Per N4582, lambda closures are *not*:
100             // - aggregates ([expr.prim.lambda]/4)
101             // - default constructible ([expr.prim.lambda]/p21)
102             // - copy assignable ([expr.prim.lambda]/p21)
103             template
104             using could_be_lambda =
105             meta::bool_<
106             !std::is_default_constructible::value &&
107             !std::is_copy_assignable::value>;
108              
109             template
110             constexpr box_compress box_compression_(...)
111             {
112             return box_compress::none;
113             }
114             template
115             meta::strict_and, meta::not_>
116             #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 6 && __GNUC_MINOR__ < 2
117             // GCC 6.0 & 6.1 find empty lambdas' implicit conversion to function pointer
118             // when doing overload resolution for function calls. That causes hard errors.
119             // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71117
120             , meta::not_>
121             #endif
122             >>>
123             constexpr box_compress box_compression_(long)
124             {
125             return box_compress::ebo;
126             }
127             #ifndef RANGES_WORKAROUND_MSVC_249830
128             // MSVC pukes passing non-constant-expression objects to constexpr
129             // functions, so do not coalesce.
130             template
131             meta::strict_and, std::is_trivial, std::is_default_constructible>>>
132             constexpr box_compress box_compression_(int)
133             {
134             return box_compress::coalesce;
135             }
136             #endif
137             template
138             constexpr box_compress box_compression()
139             {
140             return box_compression_(0);
141             }
142             }
143             /// \endcond
144              
145             template
146             detail::box_compress = detail::box_compression()>
147             class box
148             {
149             Element value;
150             public:
151             CONCEPT_REQUIRES(std::is_default_constructible::value)
152             constexpr box()
153             noexcept(std::is_nothrow_default_constructible::value)
154             : value{}
155             {}
156             template
157             CONCEPT_REQUIRES_(std::is_constructible::value &&
158             detail::is_convertible::value)>
159 4785           constexpr box(E && e)
160             noexcept(std::is_nothrow_constructible::value)
161 319           : value(static_cast(e))
162 4785           {}
163             template
164             CONCEPT_REQUIRES_(std::is_constructible::value &&
165             !detail::is_convertible::value)>
166             constexpr explicit box(E && e)
167             noexcept(std::is_nothrow_constructible::value)
168             : value(static_cast(e))
169             {}
170              
171 2662           RANGES_CXX14_CONSTEXPR Element &get() & noexcept
172             {
173 2662           return value;
174             }
175 5654           constexpr Element const &get() const & noexcept
176             {
177 5654           return value;
178             }
179             RANGES_CXX14_CONSTEXPR Element &&get() && noexcept
180             {
181             return detail::move(value);
182             }
183             };
184              
185             template
186             class box
187             : Element
188             {
189             public:
190             CONCEPT_REQUIRES(std::is_default_constructible::value)
191             constexpr box()
192             noexcept(std::is_nothrow_default_constructible::value)
193             : Element{}
194             {}
195             template
196             CONCEPT_REQUIRES_(std::is_constructible::value &&
197             detail::is_convertible::value)>
198 319           constexpr box(E && e)
199             noexcept(std::is_nothrow_constructible::value)
200             : Element(static_cast(e))
201 319           {}
202             template
203             CONCEPT_REQUIRES_(std::is_constructible::value &&
204             !detail::is_convertible::value)>
205             constexpr explicit box(E && e)
206             noexcept(std::is_nothrow_constructible::value)
207             : Element(static_cast(e))
208             {}
209              
210 154           RANGES_CXX14_CONSTEXPR Element &get() & noexcept
211             {
212 154           return *this;
213             }
214             constexpr Element const &get() const & noexcept
215             {
216             return *this;
217             }
218             RANGES_CXX14_CONSTEXPR Element &&get() && noexcept
219             {
220             return detail::move(*this);
221             }
222             };
223              
224             template
225             class box
226             {
227             static Element value;
228             public:
229             constexpr box() noexcept
230             {}
231             template
232             CONCEPT_REQUIRES_(std::is_constructible::value &&
233             detail::is_convertible::value)>
234             constexpr box(E &&) noexcept
235             {}
236             template
237             CONCEPT_REQUIRES_(std::is_constructible::value &&
238             !detail::is_convertible::value)>
239             constexpr explicit box(E &&) noexcept
240             {}
241              
242             RANGES_CXX14_CONSTEXPR Element &get() & noexcept
243             {
244             return value;
245             }
246             constexpr Element const &get() const & noexcept
247             {
248             return value;
249             }
250             RANGES_CXX14_CONSTEXPR Element &&get() && noexcept
251             {
252             return detail::move(value);
253             }
254             };
255              
256             template
257             Element box::value;
258              
259             // Get by tag type
260             template
261             RANGES_CXX14_CONSTEXPR Element & get(box & b) noexcept
262             {
263             return b.get();
264             }
265              
266             template
267             constexpr Element const & get(box const & b) noexcept
268             {
269             return b.get();
270             }
271              
272             template
273             RANGES_CXX14_CONSTEXPR Element && get(box && b) noexcept
274             {
275             return detail::move(b).get();
276             }
277              
278             // Get by index
279             template
280             RANGES_CXX14_CONSTEXPR Element & get(box, BC> & b) noexcept
281             {
282             return b.get();
283             }
284              
285             template
286             constexpr Element const & get(box, BC> const & b) noexcept
287             {
288             return b.get();
289             }
290              
291             template
292             RANGES_CXX14_CONSTEXPR Element && get(box, BC> && b) noexcept
293             {
294             return detail::move(b).get();
295             }
296             /// @}
297             }
298             }
299              
300             #endif