CollectionImpl

CollectionImpl

CollectionLeaf

Collections

TupleTypeIndex

TupleTypeIndex

TupleTypeIndex

Macros

Line Code
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
#ifndef DataFormats_Portable_interface_PortableCollectionCommon_h
#define DataFormats_Portable_interface_PortableCollectionCommon_h

#include <cstddef>
#include <type_traits>
#include <array>

namespace portablecollection {

  // Note: if there are other uses for this, it could be moved to a central place
  template <std::size_t Start, std::size_t End, std::size_t Inc = 1, typename F>
  constexpr void constexpr_for(F&& f) {
    if constexpr (Start < End) {
      f(std::integral_constant<std::size_t, Start>());
      constexpr_for<Start + Inc, End, Inc>(std::forward<F>(f));
    }
  }

  template <std::size_t Idx, typename T>
  struct CollectionLeaf {
    CollectionLeaf() = default;
    CollectionLeaf(std::byte* buffer, int32_t elements) : layout_(buffer, elements), view_(layout_) {}
    template <std::size_t N>
    CollectionLeaf(std::byte* buffer, std::array<int32_t, N> const& sizes)
        : layout_(buffer, sizes[Idx]), view_(layout_) {
      static_assert(N >= Idx);
    }
    using Layout = T;
    using View = typename Layout::View;
    using ConstView = typename Layout::ConstView;
    Layout layout_;  //
    View view_;      //!
    // Make sure types are not void.
    static_assert(not std::is_same<T, void>::value);
  };

  template <std::size_t Idx, typename T, typename... Args>
  struct CollectionImpl : public CollectionLeaf<Idx, T>, public CollectionImpl<Idx + 1, Args...> {
    CollectionImpl() = default;
    CollectionImpl(std::byte* buffer, int32_t elements) : CollectionLeaf<Idx, T>(buffer, elements) {}

    template <std::size_t N>
    CollectionImpl(std::byte* buffer, std::array<int32_t, N> const& sizes)
        : CollectionLeaf<Idx, T>(buffer, sizes),
          CollectionImpl<Idx + 1, Args...>(CollectionLeaf<Idx, T>::layout_.metadata().nextByte(), sizes) {}
  };

  template <std::size_t Idx, typename T>
  struct CollectionImpl<Idx, T> : public CollectionLeaf<Idx, T> {
    CollectionImpl() = default;
    CollectionImpl(std::byte* buffer, int32_t elements) : CollectionLeaf<Idx, T>(buffer, elements) {}

    template <std::size_t N>
    CollectionImpl(std::byte* buffer, std::array<int32_t, N> const& sizes) : CollectionLeaf<Idx, T>(buffer, sizes) {
      static_assert(N == Idx + 1);
    }
  };

  template <typename... Args>
  struct Collections : public CollectionImpl<0, Args...> {};

  // return the type at the Idx position in Args...
  template <std::size_t Idx, typename... Args>
  using TypeResolver = typename std::tuple_element<Idx, std::tuple<Args...>>::type;

  // count how many times the type T occurs in Args...
  template <typename T, typename... Args>
  inline constexpr std::size_t typeCount = ((std::is_same<T, Args>::value ? 1 : 0) + ... + 0);

  // count the non-void elements of Args...
  template <typename... Args>
  inline constexpr std::size_t membersCount = sizeof...(Args);

  // if the type T occurs in Tuple, TupleTypeIndex has a static member value with the corresponding index;
  // otherwise there is no such data  member.
  template <typename T, typename Tuple>
  struct TupleTypeIndex {};

  template <typename T, typename... Args>
  struct TupleTypeIndex<T, std::tuple<T, Args...>> {
    static_assert(typeCount<T, Args...> == 0, "the requested type appears more than once among the arguments");
    static constexpr std::size_t value = 0;
  };

  template <typename T, typename U, typename... Args>
  struct TupleTypeIndex<T, std::tuple<U, Args...>> {
    static_assert(not std::is_same_v<T, U>);
    static_assert(typeCount<T, Args...> == 1, "the requested type does not appear among the arguments");
    static constexpr std::size_t value = 1 + TupleTypeIndex<T, std::tuple<Args...>>::value;
  };

  // if the type T occurs in Args..., TypeIndex has a static member value with the corresponding index;
  // otherwise there is no such data  member.
  template <typename T, typename... Args>
  using TypeIndex = TupleTypeIndex<T, std::tuple<Args...>>;

  // return the index where the type T occurs in Args...
  template <typename T, typename... Args>
  inline constexpr std::size_t typeIndex = TypeIndex<T, Args...>::value;

}  // namespace portablecollection

#endif  // DataFormats_Portable_interface_PortableCollectionCommon_h