Dune Core Modules (2.9.1)

rangeutilities.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5#ifndef DUNE_COMMON_RANGE_UTILITIES_HH
6#define DUNE_COMMON_RANGE_UTILITIES_HH
7
9#include <algorithm>
10#include <utility>
11#include <type_traits>
12#include <bitset>
13
21namespace Dune
22{
23
34 template <typename T,
35 typename std::enable_if<IsIterable<T>::value, int>::type = 0>
36 typename T::value_type
37 max_value(const T & v) {
38 using std::max_element;
39 return *max_element(v.begin(), v.end());
40 }
41
42 template <typename T,
43 typename std::enable_if<!IsIterable<T>::value, int>::type = 0>
44 const T & max_value(const T & v) { return v; }
45
51 template <typename T,
52 typename std::enable_if<IsIterable<T>::value, int>::type = 0>
53 typename T::value_type
54 min_value(const T & v) {
55 using std::min_element;
56 return *min_element(v.begin(), v.end());
57 }
58
59 template <typename T,
60 typename std::enable_if<!IsIterable<T>::value, int>::type = 0>
61 const T & min_value(const T & v) { return v; }
62
68 template <typename T,
69 typename std::enable_if<IsIterable<T>::value, int>::type = 0>
70 bool any_true(const T & v) {
71 bool b = false;
72 for (const auto & e : v)
73 b = b or bool(e);
74 return b;
75 }
76
77 template <typename T,
78 typename std::enable_if<!IsIterable<T>::value, int>::type = 0>
79 bool any_true(const T & v) { return v; }
80
81 template<std::size_t N>
82 bool any_true(const std::bitset<N> & b)
83 {
84 return b.any();
85 }
86
92 template <typename T,
93 typename std::enable_if<IsIterable<T>::value, int>::type = 0>
94 bool all_true(const T & v) {
95 bool b = true;
96 for (const auto & e : v)
97 b = b and bool(e);
98 return b;
99 }
100
101 template <typename T,
102 typename std::enable_if<!IsIterable<T>::value, int>::type = 0>
103 bool all_true(const T & v) { return v; }
104
105 template<std::size_t N>
106 bool all_true(const std::bitset<N> & b)
107 {
108 return b.all();
109 }
110
111
112
113 namespace Impl
114 {
115
116 template <class T>
117 class IntegralRangeIterator
118 {
119 public:
120 typedef std::random_access_iterator_tag iterator_category;
121 typedef T value_type;
122 typedef std::make_signed_t<T> difference_type;
123 typedef const T *pointer;
124 typedef T reference;
125
126 constexpr IntegralRangeIterator() noexcept : value_(0) {}
127 constexpr explicit IntegralRangeIterator(value_type value) noexcept : value_(value) {}
128
129 pointer operator->() const noexcept { return &value_; }
130 constexpr reference operator*() const noexcept { return value_; }
131
132 constexpr reference operator[]( difference_type n ) const noexcept { return (value_ + n); }
133
134 constexpr bool operator==(const IntegralRangeIterator & other) const noexcept { return (value_ == other.value_); }
135 constexpr bool operator!=(const IntegralRangeIterator & other) const noexcept { return (value_ != other.value_); }
136
137 constexpr bool operator<(const IntegralRangeIterator & other) const noexcept { return (value_ <= other.value_); }
138 constexpr bool operator<=(const IntegralRangeIterator & other) const noexcept { return (value_ <= other.value_); }
139 constexpr bool operator>(const IntegralRangeIterator & other) const noexcept { return (value_ >= other.value_); }
140 constexpr bool operator>=(const IntegralRangeIterator & other) const noexcept { return (value_ >= other.value_); }
141
142 IntegralRangeIterator& operator++() noexcept { ++value_; return *this; }
143 IntegralRangeIterator operator++(int) noexcept { IntegralRangeIterator copy( *this ); ++(*this); return copy; }
144
145 IntegralRangeIterator& operator--() noexcept { --value_; return *this; }
146 IntegralRangeIterator operator--(int) noexcept { IntegralRangeIterator copy( *this ); --(*this); return copy; }
147
148 IntegralRangeIterator& operator+=(difference_type n) noexcept { value_ += n; return *this; }
149 IntegralRangeIterator& operator-=(difference_type n) noexcept { value_ -= n; return *this; }
150
151 friend constexpr IntegralRangeIterator operator+(const IntegralRangeIterator &a, difference_type n) noexcept { return IntegralRangeIterator(a.value_ + n); }
152 friend constexpr IntegralRangeIterator operator+(difference_type n, const IntegralRangeIterator &a) noexcept { return IntegralRangeIterator(a.value_ + n); }
153 friend constexpr IntegralRangeIterator operator-(const IntegralRangeIterator &a, difference_type n) noexcept { return IntegralRangeIterator(a.value_ - n); }
154
155 constexpr difference_type operator-(const IntegralRangeIterator &other) const noexcept { return (static_cast<difference_type>(value_) - static_cast<difference_type>(other.value_)); }
156
157 private:
158 value_type value_;
159 };
160
161 } // namespace Impl
162
163
164
173 template <class T>
175 {
176 public:
178 typedef T value_type;
180 typedef Impl::IntegralRangeIterator<T> iterator;
182 typedef std::make_unsigned_t<T> size_type;
183
185 constexpr IntegralRange(value_type from, value_type to) noexcept : from_(from), to_(to) {}
187 constexpr explicit IntegralRange(value_type to) noexcept : from_(0), to_(to) {}
189 constexpr IntegralRange(std::pair<value_type, value_type> range) noexcept : from_(range.first), to_(range.second) {}
190
192 constexpr iterator begin() const noexcept { return iterator(from_); }
194 constexpr iterator end() const noexcept { return iterator(to_); }
195
197 constexpr value_type operator[](const value_type &i) const noexcept { return (from_ + i); }
198
200 constexpr bool empty() const noexcept { return (from_ == to_); }
202 constexpr size_type size() const noexcept { return (static_cast<size_type>(to_) - static_cast<size_type>(from_)); }
203
204 private:
205 value_type from_, to_;
206 };
207
208
223 template <class T, T to, T from = 0>
225 {
226 template <T ofs, T... i>
227 static std::integer_sequence<T, (i+ofs)...> shift_integer_sequence(std::integer_sequence<T, i...>);
228
229 public:
231 typedef T value_type;
233 typedef Impl::IntegralRangeIterator<T> iterator;
235 typedef std::make_unsigned_t<T> size_type;
236
238 typedef decltype(shift_integer_sequence<from>(std::make_integer_sequence<T, to-from>())) integer_sequence;
239
241 constexpr StaticIntegralRange() noexcept = default;
242
244 constexpr operator IntegralRange<T>() const noexcept { return {from, to}; }
246 constexpr operator integer_sequence() const noexcept { return {}; }
247
249 static constexpr iterator begin() noexcept { return iterator(from); }
251 static constexpr iterator end() noexcept { return iterator(to); }
252
254 template <class U, U i>
255 constexpr auto operator[](const std::integral_constant<U, i> &) const noexcept
256 -> std::integral_constant<value_type, from + static_cast<value_type>(i)>
257 {
258 return {};
259 }
260
262 constexpr value_type operator[](const size_type &i) const noexcept { return (from + static_cast<value_type>(i)); }
263
265 static constexpr std::integral_constant<bool, from == to> empty() noexcept { return {}; }
267 static constexpr std::integral_constant<size_type, static_cast<size_type>(to) - static_cast<size_type>(from) > size() noexcept { return {}; }
268 };
269
279 template<class T, class U,
280 std::enable_if_t<std::is_same<std::decay_t<T>, std::decay_t<U>>::value, int> = 0,
281 std::enable_if_t<std::is_integral<std::decay_t<T>>::value, int> = 0>
282 inline static IntegralRange<std::decay_t<T>> range(T &&from, U &&to) noexcept
283 {
284 return IntegralRange<std::decay_t<T>>(std::forward<T>(from), std::forward<U>(to));
285 }
286
287 template<class T, std::enable_if_t<std::is_integral<std::decay_t<T>>::value, int> = 0>
288 inline static IntegralRange<std::decay_t<T>> range(T &&to) noexcept
289 {
290 return IntegralRange<std::decay_t<T>>(std::forward<T>(to));
291 }
292
293 template<class T, std::enable_if_t<std::is_enum<std::decay_t<T>>::value, int> = 0>
294 inline static IntegralRange<std::underlying_type_t<std::decay_t<T>>> range(T &&to) noexcept
295 {
296 return IntegralRange<std::underlying_type_t<std::decay_t<T>>>(std::forward<T>(to));
297 }
298
299 template<class T, T from, T to>
300 inline static StaticIntegralRange<T, to, from> range(std::integral_constant<T, from>, std::integral_constant<T, to>) noexcept
301 {
302 return {};
303 }
304
305 template<class T, T to>
306 inline static StaticIntegralRange<T, to> range(std::integral_constant<T, to>) noexcept
307 {
308 return {};
309 }
310
311
312
317
322
323 namespace Impl
324 {
325
326 // Helper class to mimic a pointer for proxy objects.
327 // This is needed to implement operator-> on an iterator
328 // using proxy-values. It stores the proxy value but
329 // provides operator-> like a pointer.
330 template<class ProxyType>
331 class PointerProxy
332 {
333 public:
334 PointerProxy(ProxyType&& p) : p_(p)
335 {}
336
337 ProxyType* operator->()
338 {
339 return &p_;
340 }
341
342 ProxyType p_;
343 };
344
345 // An iterator transforming a wrapped iterator using
346 // an unary function. It inherits the iterator-category
347 // of the underlying iterator.
348 template <class I, class F, class TransformationType, class C = typename std::iterator_traits<I>::iterator_category>
349 class TransformedRangeIterator;
350
351 template <class I, class F, class TransformationType>
352 class TransformedRangeIterator<I,F,TransformationType,std::forward_iterator_tag>
353 {
354 protected:
355
356 static decltype(auto) transform(const F& f, const I& it) {
357 if constexpr (std::is_same_v<TransformationType,IteratorTransformationTag>)
358 return f(it);
359 else
360 return f(*it);
361 }
362
363 public:
364 using iterator_category = std::forward_iterator_tag;
365 using reference = decltype(transform(std::declval<F>(), std::declval<I>()));
366 using value_type = std::decay_t<reference>;
367 using pointer = PointerProxy<value_type>;
368
369 // If we later want to allow standalone TransformedRangeIterators,
370 // we could customize the FunctionPointer to be a default-constructible,
371 // copy-assignable type storing a function but acting like a pointer
372 // to function.
373 using FunctionPointer = const F*;
374
375 constexpr TransformedRangeIterator(const I& it, FunctionPointer f) noexcept :
376 it_(it),
377 f_(f)
378 {}
379
380 // Explicitly initialize members. Using a plain
381 //
382 // constexpr TransformedRangeIterator() noexcept {}
383 //
384 // would default-initialize the members while
385 //
386 // constexpr TransformedRangeIterator() noexcept : it_(), f_() {}
387 //
388 // leads to value-initialization. This is a case where
389 // both are really different. If it_ is a raw pointer (i.e. POD)
390 // then default-initialization leaves it uninitialized while
391 // value-initialization zero-initializes it.
392 constexpr TransformedRangeIterator() noexcept :
393 it_(),
394 f_()
395 {}
396
397 // Dereferencing returns a value created by the function
398 constexpr reference operator*() const noexcept {
399 return transform(*f_, it_);
400 }
401
402 // Dereferencing returns a value created by the function
403 pointer operator->() const noexcept {
404 return transform(*f_, it_);
405 }
406
407 constexpr TransformedRangeIterator& operator=(const TransformedRangeIterator& other) = default;
408
409 constexpr bool operator==(const TransformedRangeIterator& other) const noexcept {
410 return (it_ == other.it_);
411 }
412
413 constexpr bool operator!=(const TransformedRangeIterator& other) const noexcept {
414 return (it_ != other.it_);
415 }
416
417 TransformedRangeIterator& operator++() noexcept {
418 ++it_;
419 return *this;
420 }
421
422 TransformedRangeIterator operator++(int) noexcept {
423 TransformedRangeIterator copy(*this);
424 ++(*this);
425 return copy;
426 }
427
428 protected:
429 I it_;
430 FunctionPointer f_;
431 };
432
433
434
435 template <class I, class F, class T>
436 class TransformedRangeIterator<I,F,T,std::bidirectional_iterator_tag> :
437 public TransformedRangeIterator<I,F,T,std::forward_iterator_tag>
438 {
439 protected:
440 using Base = TransformedRangeIterator<I,F,T,std::forward_iterator_tag>;
441 using Base::it_;
442 using Base::f_;
443 public:
444 using iterator_category = std::bidirectional_iterator_tag;
445 using reference = typename Base::reference;
446 using value_type = typename Base::value_type;
447 using pointer = typename Base::pointer;
448
449 using FunctionPointer = typename Base::FunctionPointer;
450
451 using Base::Base;
452
453 // Member functions of the forward_iterator that need
454 // to be redefined because the base class methods return a
455 // forward_iterator.
456 constexpr TransformedRangeIterator& operator=(const TransformedRangeIterator& other) = default;
457
458 TransformedRangeIterator& operator++() noexcept {
459 ++it_;
460 return *this;
461 }
462
463 TransformedRangeIterator operator++(int) noexcept {
464 TransformedRangeIterator copy(*this);
465 ++(*this);
466 return copy;
467 }
468
469 // Additional member functions of bidirectional_iterator
470 TransformedRangeIterator& operator--() noexcept {
471 --(this->it_);
472 return *this;
473 }
474
475 TransformedRangeIterator operator--(int) noexcept {
476 TransformedRangeIterator copy(*this);
477 --(*this);
478 return copy;
479 }
480 };
481
482
483
484 template <class I, class F, class T>
485 class TransformedRangeIterator<I,F,T,std::random_access_iterator_tag> :
486 public TransformedRangeIterator<I,F,T,std::bidirectional_iterator_tag>
487 {
488 protected:
489 using Base = TransformedRangeIterator<I,F,T,std::bidirectional_iterator_tag>;
490 using Base::it_;
491 using Base::f_;
492 public:
493 using iterator_category = std::random_access_iterator_tag;
494 using reference = typename Base::reference;
495 using value_type = typename Base::value_type;
496 using pointer = typename Base::pointer;
497 using difference_type = typename std::iterator_traits<I>::difference_type;
498
499 using FunctionPointer = typename Base::FunctionPointer;
500
501 using Base::Base;
502
503 // Member functions of the forward_iterator that need
504 // to be redefined because the base class methods return a
505 // forward_iterator.
506 constexpr TransformedRangeIterator& operator=(const TransformedRangeIterator& other) = default;
507
508 TransformedRangeIterator& operator++() noexcept {
509 ++it_;
510 return *this;
511 }
512
513 TransformedRangeIterator operator++(int) noexcept {
514 TransformedRangeIterator copy(*this);
515 ++(*this);
516 return copy;
517 }
518
519 // Member functions of the bidirectional_iterator that need
520 // to be redefined because the base class methods return a
521 // bidirectional_iterator.
522 TransformedRangeIterator& operator--() noexcept {
523 --(this->it_);
524 return *this;
525 }
526
527 TransformedRangeIterator operator--(int) noexcept {
528 TransformedRangeIterator copy(*this);
529 --(*this);
530 return copy;
531 }
532
533 // Additional member functions of random_access_iterator
534 TransformedRangeIterator& operator+=(difference_type n) noexcept {
535 it_ += n;
536 return *this;
537 }
538
539 TransformedRangeIterator& operator-=(difference_type n) noexcept {
540 it_ -= n;
541 return *this;
542 }
543
544 bool operator<(const TransformedRangeIterator& other) noexcept {
545 return it_<other.it_;
546 }
547
548 bool operator<=(const TransformedRangeIterator& other) noexcept {
549 return it_<=other.it_;
550 }
551
552 bool operator>(const TransformedRangeIterator& other) noexcept {
553 return it_>other.it_;
554 }
555
556 bool operator>=(const TransformedRangeIterator& other) noexcept {
557 return it_>=other.it_;
558 }
559
560 reference operator[](difference_type n) noexcept {
561 return Base::transform(*f_, it_+n);
562 }
563
564 friend
565 TransformedRangeIterator operator+(const TransformedRangeIterator& it, difference_type n) noexcept {
566 return TransformedRangeIterator(it.it_+n, it.f_);
567 }
568
569 friend
570 TransformedRangeIterator operator+(difference_type n, const TransformedRangeIterator& it) noexcept {
571 return TransformedRangeIterator(n+it.it_, it.f_);
572 }
573
574 friend
575 TransformedRangeIterator operator-(const TransformedRangeIterator& it, difference_type n) noexcept {
576 return TransformedRangeIterator(it.it_-n, it.f_);
577 }
578
579 friend
580 difference_type operator-(const TransformedRangeIterator& first, const TransformedRangeIterator& second) noexcept {
581 return first.it_-second.it_;
582 }
583 };
584
585
586 } // namespace Impl
587
588
589
626 template <class R, class F, class T=ValueTransformationTag>
628 {
629 using RawConstIterator = std::decay_t<decltype(std::declval<const R>().begin())>;
630 using RawIterator = std::decay_t<decltype(std::declval<R>().begin())>;
631
632 public:
633
640 using const_iterator = Impl::TransformedRangeIterator<RawConstIterator, F, T>;
641
648 using iterator = Impl::TransformedRangeIterator<RawIterator, F, T>;
649
656 using RawRange = std::remove_reference_t<R>;
657
661 template<class RR>
662 constexpr TransformedRangeView(RR&& rawRange, const F& f) noexcept :
663 rawRange_(std::forward<RR>(rawRange)),
664 f_(f)
665 {
666 static_assert(std::is_same_v<T, ValueTransformationTag> or std::is_same_v<T, IteratorTransformationTag>,
667 "The TransformationType passed to TransformedRangeView has to be either ValueTransformationTag or IteratorTransformationTag.");
668 }
669
678 constexpr const_iterator begin() const noexcept {
679 return const_iterator(rawRange_.begin(), &f_);
680 }
681
682 constexpr iterator begin() noexcept {
683 return iterator(rawRange_.begin(), &f_);
684 }
685
694 constexpr const_iterator end() const noexcept {
695 return const_iterator(rawRange_.end(), &f_);
696 }
697
698 constexpr iterator end() noexcept {
699 return iterator(rawRange_.end(), &f_);
700 }
701
712 template<class Dummy=R,
713 class = std::void_t<decltype(std::declval<Dummy>().size())>>
714 auto size() const
715 {
716 return rawRange_.size();
717 }
718
722 const RawRange& rawRange() const
723 {
724 return rawRange_;
725 }
726
731 {
732 return rawRange_;
733 }
734
735 private:
736 R rawRange_;
737 F f_;
738 };
739
768 template <class R, class F>
769 auto transformedRangeView(R&& range, const F& f)
770 {
771 return TransformedRangeView<R, F, ValueTransformationTag>(std::forward<R>(range), f);
772 }
773
801 template <class R, class F>
802 auto iteratorTransformedRangeView(R&& range, const F& f)
803 {
804 return TransformedRangeView<R, F, IteratorTransformationTag>(std::forward<R>(range), f);
805 }
806
807
820 template<class Range>
821 auto sparseRange(Range&& range) {
822 return Dune::iteratorTransformedRangeView(std::forward<Range>(range), [](auto&& it) {
823 return std::tuple<decltype(*it), decltype(it.index())>(*it, it.index());
824 });
825 }
826
831}
832
833#endif // DUNE_COMMON_RANGE_UTILITIES_HH
dynamic integer range for use in range-based for loops
Definition: rangeutilities.hh:175
constexpr iterator begin() const noexcept
obtain a random-access iterator to the first element
Definition: rangeutilities.hh:192
constexpr iterator end() const noexcept
obtain a random-access iterator past the last element
Definition: rangeutilities.hh:194
std::make_unsigned_t< T > size_type
unsigned integer type corresponding to value_type
Definition: rangeutilities.hh:182
Impl::IntegralRangeIterator< T > iterator
type of iterator
Definition: rangeutilities.hh:180
constexpr value_type operator[](const value_type &i) const noexcept
access specified element
Definition: rangeutilities.hh:197
constexpr bool empty() const noexcept
check whether the range is empty
Definition: rangeutilities.hh:200
constexpr IntegralRange(std::pair< value_type, value_type > range) noexcept
construct integer range std::pair
Definition: rangeutilities.hh:189
constexpr IntegralRange(value_type from, value_type to) noexcept
construct integer range [from, to)
Definition: rangeutilities.hh:185
constexpr size_type size() const noexcept
obtain number of elements in the range
Definition: rangeutilities.hh:202
constexpr IntegralRange(value_type to) noexcept
construct integer range [0, to)
Definition: rangeutilities.hh:187
T value_type
type of integers contained in the range
Definition: rangeutilities.hh:178
static integer range for use in range-based for loops
Definition: rangeutilities.hh:225
static constexpr iterator end() noexcept
obtain a random-access iterator past the last element
Definition: rangeutilities.hh:251
decltype(shift_integer_sequence< from >(std::make_integer_sequence< T, to-from >())) integer_sequence
type of corresponding std::integer_sequence
Definition: rangeutilities.hh:238
constexpr StaticIntegralRange() noexcept=default
default constructor
std::make_unsigned_t< T > size_type
unsigned integer type corresponding to value_type
Definition: rangeutilities.hh:235
T value_type
type of integers contained in the range
Definition: rangeutilities.hh:231
constexpr auto operator[](const std::integral_constant< U, i > &) const noexcept -> std::integral_constant< value_type, from+static_cast< value_type >(i)>
access specified element (static version)
Definition: rangeutilities.hh:255
static constexpr std::integral_constant< bool, from==to > empty() noexcept
check whether the range is empty
Definition: rangeutilities.hh:265
static constexpr iterator begin() noexcept
obtain a random-access iterator to the first element
Definition: rangeutilities.hh:249
constexpr value_type operator[](const size_type &i) const noexcept
access specified element (dynamic version)
Definition: rangeutilities.hh:262
Impl::IntegralRangeIterator< T > iterator
type of iterator
Definition: rangeutilities.hh:233
static constexpr std::integral_constant< size_type, static_cast< size_type >(to) - static_cast< size_type >(from) > size() noexcept
obtain number of elements in the range
Definition: rangeutilities.hh:267
A range transforming the values of another range on-the-fly.
Definition: rangeutilities.hh:628
auto size() const
Obtain the size of the range.
Definition: rangeutilities.hh:714
std::remove_reference_t< R > RawRange
Export type of the wrapped untransformed range.
Definition: rangeutilities.hh:656
Impl::TransformedRangeIterator< RawConstIterator, F, T > const_iterator
Const iterator type.
Definition: rangeutilities.hh:640
constexpr TransformedRangeView(RR &&rawRange, const F &f) noexcept
Construct from range and function.
Definition: rangeutilities.hh:662
const RawRange & rawRange() const
Export the wrapped untransformed range.
Definition: rangeutilities.hh:722
Impl::TransformedRangeIterator< RawIterator, F, T > iterator
Iterator type.
Definition: rangeutilities.hh:648
constexpr const_iterator begin() const noexcept
Obtain a iterator to the first element.
Definition: rangeutilities.hh:678
constexpr const_iterator end() const noexcept
Obtain a iterator past the last element.
Definition: rangeutilities.hh:694
RawRange & rawRange()
Export the wrapped untransformed range.
Definition: rangeutilities.hh:730
EnableIfInterOperable< T1, T2, bool >::type operator<(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition: iteratorfacades.hh:637
EnableIfInterOperable< T1, T2, bool >::type operator>(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition: iteratorfacades.hh:683
EnableIfInterOperable< T1, T2, bool >::type operator<=(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition: iteratorfacades.hh:660
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:237
EnableIfInterOperable< T1, T2, bool >::type operator>=(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition: iteratorfacades.hh:705
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition: iteratorfacades.hh:259
auto sparseRange(Range &&range)
Allow structured-binding for-loops for sparse iterators.
Definition: rangeutilities.hh:821
auto iteratorTransformedRangeView(R &&range, const F &f)
Create a TransformedRangeView using an iterator transformation.
Definition: rangeutilities.hh:802
auto transformedRangeView(R &&range, const F &f)
Create a TransformedRangeView.
Definition: rangeutilities.hh:769
Dune namespace.
Definition: alignedallocator.hh:13
STL namespace.
Tag to enable iterator based transformations in TransformedRangeView.
Definition: rangeutilities.hh:321
Tag to enable value based transformations in TransformedRangeView.
Definition: rangeutilities.hh:316
Traits for type conversions and type information.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)