48 static MPI_Datatype getType()
54 std::call_once(flag_, [] {
56 constexpr std::size_t N =
sizeof...(Members);
63 std::array<int, N> blk{}; blk.fill(1);
65 std::array<MPI_Aint, N> disp{};
67 std::array<MPI_Datatype, N> types{};
73 MPI_Get_address(&dummy, &base);
77 ( processMember<Members>(dummy, base, disp, blk, types, i++), ... );
81 MPI_Type_create_struct(N, blk.data(), disp.data(), types.data(), &tmp);
83 MPI_Type_create_resized(tmp, 0,
sizeof(Struct), &type_);
84 MPI_Type_commit(&type_);
93 static constexpr bool is_intrinsic =
false;
97 template<
class T>
struct is_std_array : std::false_type {};
98 template<
class T, std::
size_t N>
99 struct is_std_array<std::array<T, N>> : std::true_type {};
101 template <
typename T,
typename Enable =
void>
103 using Type = MPITraits<T>;
106 template <
typename T>
107 struct MpiDispatch<T, typename std::enable_if<std::is_enum<T>::value>::type> {
108 using Type = MPITraits<typename std::underlying_type<T>::type>;
111 template<auto Member,
class Dummy>
112 static void processMember(Dummy& d, MPI_Aint base,
113 std::array<MPI_Aint,
sizeof...(Members)>& disp,
114 std::array<
int,
sizeof...(Members)>& blk,
115 std::array<MPI_Datatype,
sizeof...(Members)>& types,
118 using MemberT = std::remove_reference_t<
decltype(d.*Member)>;
120 MPI_Get_address(&(d.*Member), &disp[idx]);
123 if constexpr (std::is_array_v<MemberT>) {
125 using Elem = std::remove_extent_t<MemberT>;
126 blk [idx] = std::extent_v<MemberT>;
127 types[idx] = MPITraits<Elem>::getType();
129 else if constexpr (is_std_array<MemberT>::value) {
131 using Elem =
typename MemberT::value_type;
132 blk [idx] = std::tuple_size<MemberT>::value;
133 types[idx] = MPITraits<Elem>::getType();
138 using MPIType =
typename MpiDispatch<MemberT>::Type;
139 types[idx] = MPIType::getType();
145 static inline MPI_Datatype type_ = MPI_DATATYPE_NULL;
146 static inline std::once_flag flag_;