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