This file is indexed.

/usr/include/dune/common/hybridutilities.hh is in libdune-common-dev 2.5.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_COMMON_HYBRIDUTILITIES_HH
#define DUNE_COMMON_HYBRIDUTILITIES_HH

#include <tuple>
#include <utility>

#include <dune/common/typeutilities.hh>
#include <dune/common/fvector.hh>
#include <dune/common/indices.hh>



namespace Dune {
namespace Hybrid {

namespace Impl {

  // Try if tuple_size is implemented for class
  template<class T, int i>
  constexpr auto size(const Dune::FieldVector<T, i>*, const PriorityTag<5>&)
    -> decltype(std::integral_constant<std::size_t,i>())
  {
    return {};
  }

  // Try if we have an instance of std::integer_sequence
  template<class T, T... t, class Index>
  constexpr auto size(std::integer_sequence<T, t...>, PriorityTag<4>)
  {
    using sizeAsType = std::tuple_size<decltype(std::make_tuple(t...))>;
    return std::integral_constant<std::size_t, sizeAsType::value>();
  }

  // Try if tuple_size is implemented for class
  template<class T>
  constexpr auto size(const T*, const PriorityTag<3>&)
    -> decltype(std::integral_constant<std::size_t,std::tuple_size<T>::value>())
  {
    return {};
  }

  // Try if there's a static constexpr size()
  template<class T>
  constexpr auto size(const T*, const PriorityTag<1>&)
    -> decltype(std::integral_constant<std::size_t,T::size()>())
  {
    return {};
  }

  // As a last resort try if there's a static constexpr size()
  template<class T>
  constexpr auto size(const T* t, const PriorityTag<0>&)
  {
    return t->size();
  }

} // namespace Impl



/**
 * \brief Size query
 *
 * \ingroup HybridUtilities
 *
 * \tparam T Type of container whose size is queried
 *
 * \param t Container whose size is queried
 *
 * \return Size of t
 *
 * If the size of t is known at compile type the size is
 * returned as std::integral_constant<std::size_t, size>.
 * Otherwise the result of t.size() is returned.
 *
 * Supported types for deriving the size at compile time are:
 * * instances of std::integer_sequence
 * * all types std::tuple_size is implemented for
 * * all typed that have a static method ::size()
 * * instances of Dune::FieldVector
 */
template<class T>
constexpr auto size(const T& t)
{
  return Impl::size(&t, PriorityTag<42>());
}



namespace Impl {

  template<class Container, class Index,
    std::enable_if_t<IsTuple<std::decay_t<Container>>::value, int> = 0>
  constexpr decltype(auto) elementAt(Container&& c, Index&&, PriorityTag<2>)
  {
    return std::get<std::decay_t<Index>::value>(c);
  }

  template<class T, T... t, class Index>
  constexpr decltype(auto) elementAt(std::integer_sequence<T, t...> c, Index&&, PriorityTag<1>)
  {
    return std::get<std::decay_t<Index>::value>(std::make_tuple(std::integral_constant<T, t>()...));
  }

  template<class Container, class Index>
  constexpr decltype(auto) elementAt(Container&& c, Index&& i, PriorityTag<0>)
  {
    return c[i];
  }

} // namespace Impl



/**
 * \brief Get element at given position from container
 *
 * \ingroup HybridUtilities
 *
 * \tparam Container Type of given container
 * \tparam Index Type of index
 *
 * \param c Given container
 * \param i Index of element to obtain
 *
 * \return The element at position i, i.e. c[i]
 *
 * If this returns the i-th entry of c. It supports the following
 * containers
 * * Containers providing dynamic access via operator[]
 * * Heterogenous containers providing access via operator[](integral_constant<...>)
 * * std::tuple<...>
 * * std::integer_sequence
 */
template<class Container, class Index>
constexpr decltype(auto) elementAt(Container&& c, Index&& i)
{
  return Impl::elementAt(std::forward<Container>(c), std::forward<Index>(i), PriorityTag<42>());
}



namespace Impl {

  template<class Begin, class End>
  class StaticIntegralRange
  {
  public:

    template<std::size_t i>
    constexpr auto operator[](Dune::index_constant<i>) const
    {
      return std::integral_constant<typename Begin::value_type, Begin::value+i>();
    }

    static constexpr auto size()
    {
      return std::integral_constant<typename Begin::value_type, End::value - Begin::value>();
    }
  };

  template<class T>
  class DynamicIntegralRange
  {
  public:
    constexpr DynamicIntegralRange(const T& begin, const T& end):
      begin_(begin),
      end_(end)
    {}

    constexpr auto size() const
    {
      return end_ - begin_;
    }

    constexpr T operator[](const T&i) const
    { return begin_+i; }

  private:
    T begin_;
    T end_;
  };

  template<class Begin, class End,
    std::enable_if_t<IsIntegralConstant<Begin>::value and IsIntegralConstant<End>::value, int> = 0>
  constexpr auto integralRange(const Begin& begin, const End& end, const PriorityTag<1>&)
  {
    static_assert(Begin::value <= End::value, "You cannot create an integralRange where end<begin");
    return Impl::StaticIntegralRange<Begin,End>();
  }

  // This should be constexpr but gcc-4.9 does not support
  // the relaxed constexpr requirements. Hence for beeing
  // constexpr the function body can only contain a return
  // statement and no assertion before this.
  template<class Begin, class End>
  auto integralRange(const Begin& begin, const End& end, const PriorityTag<0>&)
  {
    assert(begin <= end);
    return Impl::DynamicIntegralRange<End>(begin, end);
  }

} // namespace Impl



/**
 * \brief Create an integral range
 *
 * \ingroup HybridUtilities
 *
 * \tparam Begin Type of begin entry of the range
 * \tparam End Type of end entry of the range
 *
 * \param begin First entry of the range
 * \param end One past the last entry of the range
 *
 * \returns An object encoding the given range
 *
 * If Begin and End are both instances of type
 * std::integral_constant, the returned range
 * encodes begin and end statically.
 */
template<class Begin, class End>
constexpr auto integralRange(const Begin& begin, const End& end)
{
  return Impl::integralRange(begin, end, PriorityTag<42>());
}

/**
 * \brief Create an integral range starting from 0
 *
 * \ingroup HybridUtilities
 *
 * \tparam End Type of end entry of the range
 *
 * \param end One past the last entry of the range
 *
 * \returns An object encoding the given range
 *
 * This is a short cut for integralRange(_0, end).
 */
template<class End>
constexpr auto integralRange(const End& end)
{
  return Impl::integralRange(Dune::Indices::_0, end, PriorityTag<42>());
}



namespace Impl {

  template<class T>
  void evaluateFoldExpression(std::initializer_list<T>&&)
  {}

  template<class Range, class F, class Index, Index... i>
  constexpr void forEachIndex(Range&& range, F&& f, std::integer_sequence<Index, i...>)
  {
    evaluateFoldExpression<int>({(f(Hybrid::elementAt(range, std::integral_constant<Index,i>())), 0)...});
  }

  template<class F, class Index, Index... i>
  constexpr void forEach(std::integer_sequence<Index, i...> range, F&& f, PriorityTag<2>)
  {
    evaluateFoldExpression<int>({(f(std::integral_constant<Index,i>()), 0)...});
  }


  template<class Range, class F,
    std::enable_if_t<IsIntegralConstant<decltype(Hybrid::size(std::declval<Range>()))>::value, int> = 0>
  constexpr void forEach(Range&& range, F&& f, PriorityTag<1>)
  {
    auto size = Hybrid::size(range);
    auto indices = std::make_index_sequence<size>();
    forEachIndex(std::forward<Range>(range), std::forward<F>(f), indices);
  }

  template<class Range, class F>
  constexpr void forEach(Range&& range, F&& f, PriorityTag<0>)
  {
    for(std::size_t i=0; i<range.size(); ++i)
      f(range[i]);
    // \todo Switch to real range for once DynamicIntegralRange has proper iterators
    //  for(auto e : range)
    //    f(e);
  }

} // namespace Impl



/**
 * \brief Range based for loop
 *
 * \ingroup HybridUtilities
 *
 * \tparam Range Type of given range
 * \tparam F Type of given predicate
 *
 * \param range The range to loop over
 * \param f A predicate that will be called with each entry of the range
 *
 * This supports looping over the following ranges
 * * ranges obtained from integralRange()
 * * all ranges that provide Hybrid::size() and Hybrid::elementAt()
 *
 * This especially included instances of std::integer_sequence,
 * std::tuple, Dune::TupleVector, and Dune::MultiTypeBlockVector.
 */
template<class Range, class F>
constexpr void forEach(Range&& range, F&& f)
{
  Impl::forEach(std::forward<Range>(range), std::forward<F>(f), PriorityTag<42>());
}



/**
 * \brief Accumulate values
 *
 * \ingroup HybridUtilities
 *
 * \tparam Range Type of given range
 * \tparam T Type of accumulated value
 * \tparam F Type of binary accumulation operator
 *
 * \param range The range of values to accumulate
 * \param value Initial value for accumulation
 * \param f Binary operator for accumulation
 *
 * This supports looping over the same ranges as Hybrid::forEach
 */
template<class Range, class T, class F>
T accumulate(Range&& range, T value, F&& f)
{
  forEach(std::forward<Range>(range), [&](auto&& entry) {
    value = f(value, entry);
  });
  return value;
}



namespace Impl {

  template<class IfFunc, class ElseFunc>
  constexpr decltype(auto) ifElse(std::true_type, IfFunc&& ifFunc, ElseFunc&& elseFunc)
  {
    return ifFunc([](auto&& x) -> decltype(auto) { return std::forward<decltype(x)>(x);});
  }

  template<class IfFunc, class ElseFunc>
  constexpr decltype(auto) ifElse(std::false_type, IfFunc&& ifFunc, ElseFunc&& elseFunc)
  {
    return elseFunc([](auto&& x) -> decltype(auto) { return std::forward<decltype(x)>(x);});
  }

  template<class IfFunc, class ElseFunc>
  decltype(auto) ifElse(const bool& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc)
  {
    if (condition)
      return ifFunc([](auto&& x) -> decltype(auto) { return std::forward<decltype(x)>(x);});
    else
      return elseFunc([](auto&& x) -> decltype(auto) { return std::forward<decltype(x)>(x);});
  }

} // namespace Impl



/**
 * \brief A conditional expression
 *
 * \ingroup HybridUtilities
 *
 * This will call either ifFunc or elseFunc depending
 * on the condition. In any case a single argument
 * will be passed to the called function. This will always
 * be the indentity function. Passing an expression through
 * this function will lead to lazy evaluation. This way both
 * 'branches' can contain expressions that are only valid
 * within this branch if the condition is a std::integral_constant<bool,*>.
 *
 * In order to do this, the passed functors must have a single
 * argument of type auto.
 *
 * Due to the lazy evaluation mechanism and support for
 * std::integral_constant<bool,*> this allows to emulate
 * a static if statement.
 */
template<class Condition, class IfFunc, class ElseFunc>
decltype(auto) ifElse(const Condition& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc)
{
  return Impl::ifElse(condition, std::forward<IfFunc>(ifFunc), std::forward<ElseFunc>(elseFunc));
}

/**
 * \brief A conditional expression
 *
 * \ingroup HybridUtilities
 *
 * This provides an ifElse conditional with empty else clause.
 */
template<class Condition, class IfFunc>
void ifElse(const Condition& condition, IfFunc&& ifFunc)
{
  ifElse(condition, std::forward<IfFunc>(ifFunc), [](auto&& i) {});
}



namespace Impl {

  template<class T1, class T2>
  constexpr auto equals(const T1& t1, const T2& t2, PriorityTag<1>) -> decltype(T1::value, T2::value, std::integral_constant<bool,T1::value == T2::value>())
  { return {}; }

  template<class T1, class T2>
  constexpr auto equals(const T1& t1, const T2& t2, PriorityTag<0>)
  {
    return t1==t2;
  }

} // namespace Impl



/**
 * \brief Equality comparison
 *
 * \ingroup HybridUtilities
 *
 * If both types have a static member value, the result of comparing
 * these is returned as std::integral_constant<bool, *>. Otherwise
 * the result of a runtime comparison of t1 and t2 is directly returned.
 */
template<class T1, class T2>
constexpr auto equals(T1&& t1,  T2&& t2)
{
  return Impl::equals(std::forward<T1>(t1), std::forward<T2>(t2), PriorityTag<1>());
}



namespace Impl {

  template<class Result, class T, class Value, class Branches, class ElseBranch>
  constexpr Result switchCases(std::integer_sequence<T>, const Value& value, Branches&& branches, ElseBranch&& elseBranch)
  {
    return elseBranch();
  }

  template<class Result, class T, T t0, T... tt, class Value, class Branches, class ElseBranch>
  constexpr Result switchCases(std::integer_sequence<T, t0, tt...>, const Value& value, Branches&& branches, ElseBranch&& elseBranch)
  {
    return ifElse(
        Hybrid::equals(std::integral_constant<T, t0>(), value),
      [&](auto id) -> decltype(auto) {
        return id(branches)(std::integral_constant<T, t0>());
      }, [&](auto id) -> decltype(auto) {
        return Impl::switchCases<Result>(id(std::integer_sequence<T, tt...>()), value, branches, elseBranch);
    });
  }

} // namespace Impl



/**
 * \brief Switch statement
 *
 * \ingroup HybridUtilities
 *
 * \tparam Cases Type of case range
 * \tparam Value Type of value to check against the cases
 * \tparam Branches Type of branch function
 * \tparam ElseBranch Type of branch function
 *
 * \param cases A range of cases to check for
 * \param value The value to check against the cases
 * \param branches A callback that will be executed with matching entry from case list
 * \param elseBranch A callback that will be executed if no other entry matches
 *
 * Value is checked against all entries of the given range.
 * If one matches, then branches is executed with the matching
 * value as single argument. If the range is an std::integer_sequence,
 * the value is passed as std::integral_constant.
 * If non of the entries matches, then elseBranch is executed
 * without any argument.
 *
 * Notice that this short circuits, e.g., if one case matches,
 * the others are no longer evaluated.
 *
 * The return value will be deduced from the else branch.
 */
template<class Cases, class Value, class Branches, class ElseBranch>
constexpr decltype(auto) switchCases(const Cases& cases, const Value& value, Branches&& branches, ElseBranch&& elseBranch)
{
  return Impl::switchCases<decltype(elseBranch())>(cases, value, std::forward<Branches>(branches), std::forward<ElseBranch>(elseBranch));
}

/**
 * \brief Switch statement
 *
 * \ingroup HybridUtilities
 *
 * \tparam Cases Type of case range
 * \tparam Value Type of value to check against the cases
 * \tparam Branches Type of branch function
 *
 * \param cases A range of cases to check for
 * \param value The value to check against the cases
 * \param branches A callback that will be executed with matching entry from case list
 *
 * Value is checked against all entries of the given range.
 * If one matches, then branches is executed with the matching
 * value as single argument. If the range is an std::integer_sequence,
 * the value is passed as std::integral_constant.
 * If non of the entries matches, then elseBranch is executed
 * without any argument.
 */
template<class Cases, class Value, class Branches>
constexpr void switchCases(const Cases& cases, const Value& value, Branches&& branches)
{
  return Impl::switchCases<void>(cases, value, std::forward<Branches>(branches), []() {});
}


} // namespace Hybrid
} // namespace Dune


#endif // #ifndef DUNE_COMMON_HYBRIDUTILITIES_HH