Utility.hpp 3.27 KB
Newer Older
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
#pragma once

#include <memory>
#include <type_traits>
#include <vector>

#if AMDIS_HAS_CXX_CONSTEXPR_IF
#define IF_CONSTEXPR if constexpr
#else
#define IF_CONSTEXPR if
#endif

namespace AMDiS
{
  /// \brief Remove cv and ref qualifiers of type T.
  /**
   * If the type T is a reference type, provides the member typedef type which
   * is the type referred to by T with its topmost cv-qualifiers removed.
   * Otherwise type is T with its topmost cv-qualifiers removed.
   *
   * Note: This is a backport of c++20 std::remove_cvref
   **/
  template< class T >
  struct remove_cvref
  {
    using type = std::remove_cv_t<std::remove_reference_t<T>>;
  };

  /// Helper alias template for \ref remove_cvref
  template< class T >
  using remove_cvref_t = typename remove_cvref<T>::type;


  namespace Impl
  {
    template <class T>
    struct UnderlyingType
    {
      using type = remove_cvref_t<T>;
    };

    template <class T>
    struct UnderlyingType<std::reference_wrapper<T>>
    {
      using type = std::remove_cv_t<T>;
    };
  }

  /// \brief strip reference_wrapper, const, volatile, and references from type T
  template <class T>
  using Underlying_t = typename Impl::UnderlyingType<T>::type;


  /// Macro for forwarding universal references to obj
  #define FWD(obj) std::forward<decltype(obj)>(obj)

  /// A decay version of decltype, similar to GCCs __typeof__
  #define TYPEOF(...) remove_cvref_t<decltype(__VA_ARGS__)>

  /// Extract the static value of an integral_constant variable
  #define VALUE(...) TYPEOF(__VA_ARGS__)::value

  /// Create a unique_ptr by copy/move construction
  template <class Obj>
  auto makeUniquePtr(Obj&& obj)
  {
    return std::make_unique<TYPEOF(obj)>(FWD(obj));
  }

  // ---------------------------------------------------------------------------

  // base template for tuple size, must implement a static value member
  template <class TupleType>
  struct TupleSize;

  // utility constant returning the value of the tuple size
  template <class TupleType>
  constexpr std::size_t TupleSize_v = TupleSize<TupleType>::value;


  // base template for retrieving the tuple element type, must implement the type member `type`
  template <size_t I, class TupleType>
  struct TupleElement;

  // base template for retrieving the tuple element type
  template <size_t I, class TupleType>
  using TupleElement_t = typename TupleElement<I, TupleType>::type;


  /// A variadic type list
  template <class... Ts>
  struct Types {};

  template <class... Ts>
  using Types_t = Types<remove_cvref_t<Ts>...>;


  template <class... T>
  struct TupleSize<Types<T...>>
    : std::integral_constant<std::size_t, sizeof...(T)> {};

  template <size_t I, class Head, class... Tail>
  struct TupleElement<I, Types<Head, Tail...>>
  {
    using type = typename TupleElement<I-1, Types<Tail...>>::type;
  };

  template <class Head, class... Tail>
  struct TupleElement<0, Types<Head, Tail...>>
  {
    using type = Head;
  };


  /// Alias that indicates ownership of resources
  template <class T>
  using owner = T;


  // ---------------------------------------------------------------------------


  /// generalization of get<tuple>, get<array> for vectors
  template <std::size_t I, class T, class A>
  T const& get(std::vector<T,A> const& vec)
  {
      return vec[I];
  }

} // end namespace AMDiS