1bf215546Sopenharmony_ci//
2bf215546Sopenharmony_ci// Copyright 2013 Francisco Jerez
3bf215546Sopenharmony_ci//
4bf215546Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci// copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci// to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci// and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci// Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci//
11bf215546Sopenharmony_ci// The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci// all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci//
14bf215546Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18bf215546Sopenharmony_ci// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19bf215546Sopenharmony_ci// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20bf215546Sopenharmony_ci// OTHER DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci//
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#ifndef CLOVER_UTIL_RANGE_HPP
24bf215546Sopenharmony_ci#define CLOVER_UTIL_RANGE_HPP
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include <array>
27bf215546Sopenharmony_ci#include <vector>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "util/adaptor.hpp"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_cinamespace clover {
32bf215546Sopenharmony_ci   ///
33bf215546Sopenharmony_ci   /// Class that identifies container types where the elements of a
34bf215546Sopenharmony_ci   /// range can be stored by the type conversion operator.
35bf215546Sopenharmony_ci   ///
36bf215546Sopenharmony_ci   /// \a T identifies the range element type.
37bf215546Sopenharmony_ci   ///
38bf215546Sopenharmony_ci   template<typename T, typename V>
39bf215546Sopenharmony_ci   struct range_store_traits;
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci   template<typename T, typename S>
42bf215546Sopenharmony_ci   struct range_store_traits<T, std::vector<S>> {
43bf215546Sopenharmony_ci      typedef void enable;
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci      template<typename R>
46bf215546Sopenharmony_ci      static std::vector<S>
47bf215546Sopenharmony_ci      create(const R &r) {
48bf215546Sopenharmony_ci         return { r.begin(), r.end() };
49bf215546Sopenharmony_ci      }
50bf215546Sopenharmony_ci   };
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   template<typename T, typename S, std::size_t N>
53bf215546Sopenharmony_ci   struct range_store_traits<T, std::array<S, N>> {
54bf215546Sopenharmony_ci      typedef void enable;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci      template<typename R>
57bf215546Sopenharmony_ci      static std::array<S, N>
58bf215546Sopenharmony_ci      create(const R &r) {
59bf215546Sopenharmony_ci         std::array<S, N> v;
60bf215546Sopenharmony_ci         assert(r.size() == v.size());
61bf215546Sopenharmony_ci         copy(r, v.begin());
62bf215546Sopenharmony_ci         return v;
63bf215546Sopenharmony_ci      }
64bf215546Sopenharmony_ci   };
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   namespace detail {
67bf215546Sopenharmony_ci      ///
68bf215546Sopenharmony_ci      /// Common functionality that is shared by other implementations
69bf215546Sopenharmony_ci      /// of the container concept.
70bf215546Sopenharmony_ci      ///
71bf215546Sopenharmony_ci      template<typename R, typename I, typename CI>
72bf215546Sopenharmony_ci      class basic_range {
73bf215546Sopenharmony_ci      public:
74bf215546Sopenharmony_ci         typedef I iterator;
75bf215546Sopenharmony_ci         typedef CI const_iterator;
76bf215546Sopenharmony_ci         typedef typename std::iterator_traits<iterator>::value_type value_type;
77bf215546Sopenharmony_ci         typedef typename std::iterator_traits<iterator>::reference
78bf215546Sopenharmony_ci            reference;
79bf215546Sopenharmony_ci         typedef typename std::iterator_traits<const_iterator>::reference
80bf215546Sopenharmony_ci            const_reference;
81bf215546Sopenharmony_ci         typedef typename std::iterator_traits<iterator>::difference_type
82bf215546Sopenharmony_ci            difference_type;
83bf215546Sopenharmony_ci         typedef std::size_t size_type;
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci         bool
86bf215546Sopenharmony_ci         operator==(const basic_range &r) const {
87bf215546Sopenharmony_ci            return *static_cast<const R *>(this) == r;
88bf215546Sopenharmony_ci         }
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci         bool
91bf215546Sopenharmony_ci         operator!=(const basic_range &r) const {
92bf215546Sopenharmony_ci            return !(*this == r);
93bf215546Sopenharmony_ci         }
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci         iterator
96bf215546Sopenharmony_ci         begin() {
97bf215546Sopenharmony_ci            return static_cast<R *>(this)->begin();
98bf215546Sopenharmony_ci         }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci         iterator
101bf215546Sopenharmony_ci         end() {
102bf215546Sopenharmony_ci            return static_cast<R *>(this)->end();
103bf215546Sopenharmony_ci         }
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci         const_iterator
106bf215546Sopenharmony_ci         begin() const {
107bf215546Sopenharmony_ci            return static_cast<const R *>(this)->begin();
108bf215546Sopenharmony_ci         }
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci         const_iterator
111bf215546Sopenharmony_ci         end() const {
112bf215546Sopenharmony_ci            return static_cast<const R *>(this)->end();
113bf215546Sopenharmony_ci         }
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci         std::reverse_iterator<iterator>
116bf215546Sopenharmony_ci         rbegin() {
117bf215546Sopenharmony_ci            return { begin() };
118bf215546Sopenharmony_ci         }
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci         std::reverse_iterator<iterator>
121bf215546Sopenharmony_ci         rend() {
122bf215546Sopenharmony_ci            return { end() };
123bf215546Sopenharmony_ci         }
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci         reference
126bf215546Sopenharmony_ci         front() {
127bf215546Sopenharmony_ci            return *begin();
128bf215546Sopenharmony_ci         }
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci         reference
131bf215546Sopenharmony_ci         back() {
132bf215546Sopenharmony_ci            return *(end() - 1);
133bf215546Sopenharmony_ci         }
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci         bool
136bf215546Sopenharmony_ci         empty() const {
137bf215546Sopenharmony_ci            return begin() == end();
138bf215546Sopenharmony_ci         }
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci         reference
141bf215546Sopenharmony_ci         at(size_type i) {
142bf215546Sopenharmony_ci            if (i >= static_cast<const R *>(this)->size())
143bf215546Sopenharmony_ci               throw std::out_of_range("");
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci            return begin()[i];
146bf215546Sopenharmony_ci         }
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci         const_reference
149bf215546Sopenharmony_ci         at(size_type i) const {
150bf215546Sopenharmony_ci            if (i >= static_cast<const R *>(this)->size())
151bf215546Sopenharmony_ci               throw std::out_of_range("");
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci            return begin()[i];
154bf215546Sopenharmony_ci         }
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci         reference
157bf215546Sopenharmony_ci         operator[](size_type i) {
158bf215546Sopenharmony_ci            return begin()[i];
159bf215546Sopenharmony_ci         }
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci         const_reference
162bf215546Sopenharmony_ci         operator[](size_type i) const {
163bf215546Sopenharmony_ci            return begin()[i];
164bf215546Sopenharmony_ci         }
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci         template<typename V>
167bf215546Sopenharmony_ci         using store_traits = range_store_traits<
168bf215546Sopenharmony_ci               typename std::remove_cv<value_type>::type, V
169bf215546Sopenharmony_ci            >;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci         template<typename V,
172bf215546Sopenharmony_ci                  typename = typename store_traits<V>::enable>
173bf215546Sopenharmony_ci         operator V() const {
174bf215546Sopenharmony_ci            return store_traits<V>::create(*static_cast<const R *>(this));
175bf215546Sopenharmony_ci         }
176bf215546Sopenharmony_ci      };
177bf215546Sopenharmony_ci   }
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   ///
180bf215546Sopenharmony_ci   /// Range that contains all elements delimited by an iterator pair
181bf215546Sopenharmony_ci   /// (\a i, \a j).  Use range() as convenience constructor.
182bf215546Sopenharmony_ci   ///
183bf215546Sopenharmony_ci   template<typename I>
184bf215546Sopenharmony_ci   class iterator_range : public detail::basic_range<iterator_range<I>, I, I> {
185bf215546Sopenharmony_ci   public:
186bf215546Sopenharmony_ci      typedef detail::basic_range<iterator_range<I>, I, I> super;
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci      iterator_range() : i(), j() {
189bf215546Sopenharmony_ci      }
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci      iterator_range(I i, I j) : i(i), j(j) {
192bf215546Sopenharmony_ci      }
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci      bool
195bf215546Sopenharmony_ci      operator==(const iterator_range &r) const {
196bf215546Sopenharmony_ci         return i == r.i && j == r.j;
197bf215546Sopenharmony_ci      }
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci      I
200bf215546Sopenharmony_ci      begin() const {
201bf215546Sopenharmony_ci         return i;
202bf215546Sopenharmony_ci      }
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci      I
205bf215546Sopenharmony_ci      end() const {
206bf215546Sopenharmony_ci         return j;
207bf215546Sopenharmony_ci      }
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci      typename super::size_type
210bf215546Sopenharmony_ci      size() const {
211bf215546Sopenharmony_ci         return end() - begin();
212bf215546Sopenharmony_ci      }
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci   private:
215bf215546Sopenharmony_ci      I i, j;
216bf215546Sopenharmony_ci   };
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   namespace detail {
219bf215546Sopenharmony_ci      template<typename T>
220bf215546Sopenharmony_ci      using preferred_iterator_type = decltype(std::declval<T>().begin());
221bf215546Sopenharmony_ci   }
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   ///
224bf215546Sopenharmony_ci   /// Range that transforms the contents of a number of source ranges
225bf215546Sopenharmony_ci   /// \a os element-wise by using the provided functor \a f.  Use
226bf215546Sopenharmony_ci   /// map() as convenience constructor.
227bf215546Sopenharmony_ci   ///
228bf215546Sopenharmony_ci   template<typename F, typename... Os>
229bf215546Sopenharmony_ci   class adaptor_range :
230bf215546Sopenharmony_ci      public detail::basic_range<adaptor_range<F, Os...>,
231bf215546Sopenharmony_ci                                 detail::iterator_adaptor<
232bf215546Sopenharmony_ci                                    F, detail::preferred_iterator_type<Os>...>,
233bf215546Sopenharmony_ci                                 detail::iterator_adaptor<
234bf215546Sopenharmony_ci                                    F, detail::preferred_iterator_type<const Os>...>
235bf215546Sopenharmony_ci                                 > {
236bf215546Sopenharmony_ci   public:
237bf215546Sopenharmony_ci      typedef detail::basic_range<adaptor_range<F, Os...>,
238bf215546Sopenharmony_ci                                  detail::iterator_adaptor<
239bf215546Sopenharmony_ci                                     F, detail::preferred_iterator_type<Os>...>,
240bf215546Sopenharmony_ci                                  detail::iterator_adaptor<
241bf215546Sopenharmony_ci                                     F, detail::preferred_iterator_type<const Os>...>
242bf215546Sopenharmony_ci                                  > super;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci      template<typename G, typename... Rs>
245bf215546Sopenharmony_ci      adaptor_range(G &&f, Rs &&... os) :
246bf215546Sopenharmony_ci         f(std::forward<G>(f)), os(std::forward<Rs>(os)...) {
247bf215546Sopenharmony_ci      }
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci      bool
250bf215546Sopenharmony_ci      operator==(const adaptor_range &r) const {
251bf215546Sopenharmony_ci         return f == r.f && os == r.os;
252bf215546Sopenharmony_ci      }
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci      typename super::iterator
255bf215546Sopenharmony_ci      begin() {
256bf215546Sopenharmony_ci         return { f, tuple::map(begins(), os) };
257bf215546Sopenharmony_ci      }
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci      typename super::iterator
260bf215546Sopenharmony_ci      end() {
261bf215546Sopenharmony_ci         return { f, tuple::map(advances_by(size()),
262bf215546Sopenharmony_ci                                tuple::map(begins(), os)) };
263bf215546Sopenharmony_ci      }
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci      typename super::const_iterator
266bf215546Sopenharmony_ci      begin() const {
267bf215546Sopenharmony_ci         return { f, tuple::map(begins(), os) };
268bf215546Sopenharmony_ci      }
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci      typename super::const_iterator
271bf215546Sopenharmony_ci      end() const {
272bf215546Sopenharmony_ci         return { f, tuple::map(advances_by(size()),
273bf215546Sopenharmony_ci                                tuple::map(begins(), os)) };
274bf215546Sopenharmony_ci      }
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci      typename super::size_type
277bf215546Sopenharmony_ci      size() const {
278bf215546Sopenharmony_ci         return tuple::apply(minimum(), tuple::map(sizes(), os));
279bf215546Sopenharmony_ci      }
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   private:
282bf215546Sopenharmony_ci      F f;
283bf215546Sopenharmony_ci      std::tuple<Os...> os;
284bf215546Sopenharmony_ci   };
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   ///
287bf215546Sopenharmony_ci   /// Range that contains all elements delimited by the index pair
288bf215546Sopenharmony_ci   /// (\a i, \a j) in the source range \a r.  Use slice() as
289bf215546Sopenharmony_ci   /// convenience constructor.
290bf215546Sopenharmony_ci   ///
291bf215546Sopenharmony_ci   template<typename O>
292bf215546Sopenharmony_ci   class slice_range :
293bf215546Sopenharmony_ci      public detail::basic_range<slice_range<O>,
294bf215546Sopenharmony_ci                                 detail::preferred_iterator_type<O>,
295bf215546Sopenharmony_ci                                 detail::preferred_iterator_type<const O>> {
296bf215546Sopenharmony_ci   public:
297bf215546Sopenharmony_ci      typedef detail::basic_range<slice_range<O>,
298bf215546Sopenharmony_ci                                 detail::preferred_iterator_type<O>,
299bf215546Sopenharmony_ci                                 detail::preferred_iterator_type<const O>
300bf215546Sopenharmony_ci                                  > super;
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci      template<typename R>
303bf215546Sopenharmony_ci      slice_range(R &&r, typename super::size_type i,
304bf215546Sopenharmony_ci                  typename super::size_type j) :
305bf215546Sopenharmony_ci         o(std::forward<R>(r)), i(i), j(j) {
306bf215546Sopenharmony_ci      }
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci      bool
309bf215546Sopenharmony_ci      operator==(const slice_range &r) const {
310bf215546Sopenharmony_ci         return o == r.o && i == r.i && j == r.j;
311bf215546Sopenharmony_ci      }
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci      typename super::iterator
314bf215546Sopenharmony_ci      begin() {
315bf215546Sopenharmony_ci         return std::next(o.begin(), i);
316bf215546Sopenharmony_ci      }
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci      typename super::iterator
319bf215546Sopenharmony_ci      end() {
320bf215546Sopenharmony_ci         return std::next(o.begin(), j);
321bf215546Sopenharmony_ci      }
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci      typename super::const_iterator
324bf215546Sopenharmony_ci      begin() const {
325bf215546Sopenharmony_ci         return std::next(o.begin(), i);
326bf215546Sopenharmony_ci      }
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci      typename super::const_iterator
329bf215546Sopenharmony_ci      end() const {
330bf215546Sopenharmony_ci         return std::next(o.begin(), j);
331bf215546Sopenharmony_ci      }
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci      typename super::size_type
334bf215546Sopenharmony_ci      size() const {
335bf215546Sopenharmony_ci         return j - i;
336bf215546Sopenharmony_ci      }
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci   private:
339bf215546Sopenharmony_ci      O o;
340bf215546Sopenharmony_ci      typename super::size_type i, j;
341bf215546Sopenharmony_ci   };
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   ///
344bf215546Sopenharmony_ci   /// Create a range from an iterator pair (\a i, \a j).
345bf215546Sopenharmony_ci   ///
346bf215546Sopenharmony_ci   /// \sa iterator_range.
347bf215546Sopenharmony_ci   ///
348bf215546Sopenharmony_ci   template<typename T>
349bf215546Sopenharmony_ci   iterator_range<T>
350bf215546Sopenharmony_ci   range(T i, T j) {
351bf215546Sopenharmony_ci      return { i, j };
352bf215546Sopenharmony_ci   }
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   ///
355bf215546Sopenharmony_ci   /// Create a range of \a n elements starting from iterator \a i.
356bf215546Sopenharmony_ci   ///
357bf215546Sopenharmony_ci   /// \sa iterator_range.
358bf215546Sopenharmony_ci   ///
359bf215546Sopenharmony_ci   template<typename T>
360bf215546Sopenharmony_ci   iterator_range<T>
361bf215546Sopenharmony_ci   range(T i, typename std::iterator_traits<T>::difference_type n) {
362bf215546Sopenharmony_ci      return { i, i + n };
363bf215546Sopenharmony_ci   }
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   ///
366bf215546Sopenharmony_ci   /// Create a range by transforming the contents of a number of
367bf215546Sopenharmony_ci   /// source ranges \a rs element-wise using a provided functor \a f.
368bf215546Sopenharmony_ci   ///
369bf215546Sopenharmony_ci   /// \sa adaptor_range.
370bf215546Sopenharmony_ci   ///
371bf215546Sopenharmony_ci   template<typename F, typename... Rs>
372bf215546Sopenharmony_ci   adaptor_range<F, Rs...>
373bf215546Sopenharmony_ci   map(F &&f, Rs &&... rs) {
374bf215546Sopenharmony_ci      return { std::forward<F>(f), std::forward<Rs>(rs)... };
375bf215546Sopenharmony_ci   }
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci   ///
378bf215546Sopenharmony_ci   /// Create a range identical to another range \a r.
379bf215546Sopenharmony_ci   ///
380bf215546Sopenharmony_ci   template<typename R>
381bf215546Sopenharmony_ci   adaptor_range<identity, R>
382bf215546Sopenharmony_ci   range(R &&r) {
383bf215546Sopenharmony_ci      return { identity(), std::forward<R>(r) };
384bf215546Sopenharmony_ci   }
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci   ///
387bf215546Sopenharmony_ci   /// Create a range by taking the elements delimited by the index
388bf215546Sopenharmony_ci   /// pair (\a i, \a j) in a source range \a r.
389bf215546Sopenharmony_ci   ///
390bf215546Sopenharmony_ci   /// \sa slice_range.
391bf215546Sopenharmony_ci   ///
392bf215546Sopenharmony_ci   template<typename R>
393bf215546Sopenharmony_ci   slice_range<R>
394bf215546Sopenharmony_ci   slice(R &&r, typename slice_range<R>::size_type i,
395bf215546Sopenharmony_ci         typename slice_range<R>::size_type j) {
396bf215546Sopenharmony_ci      return { std::forward<R>(r), i, j };
397bf215546Sopenharmony_ci   }
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   ///
400bf215546Sopenharmony_ci   /// Range that behaves as a vector of references of type \a T.
401bf215546Sopenharmony_ci   ///
402bf215546Sopenharmony_ci   /// Useful because STL containers cannot contain references to
403bf215546Sopenharmony_ci   /// objects as elements.
404bf215546Sopenharmony_ci   ///
405bf215546Sopenharmony_ci   template<typename T>
406bf215546Sopenharmony_ci   class ref_vector : public adaptor_range<derefs, std::vector<T *>> {
407bf215546Sopenharmony_ci   public:
408bf215546Sopenharmony_ci      ref_vector(std::initializer_list<std::reference_wrapper<T>> il) :
409bf215546Sopenharmony_ci         adaptor_range<derefs, std::vector<T *>>(derefs(), map(addresses(), il)) {
410bf215546Sopenharmony_ci      }
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci      template<typename R>
413bf215546Sopenharmony_ci      ref_vector(R &&r) : adaptor_range<derefs, std::vector<T *>>(
414bf215546Sopenharmony_ci         derefs(), map(addresses(), std::forward<R>(r))) {
415bf215546Sopenharmony_ci      }
416bf215546Sopenharmony_ci   };
417bf215546Sopenharmony_ci}
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci#endif
420