Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-26 23:26:40

0001 #ifndef DataFormats_SoATemplate_interface_SoALayout_h
0002 #define DataFormats_SoATemplate_interface_SoALayout_h
0003 
0004 /*
0005  * Structure-of-Arrays template with "columns" and "scalars", defined through preprocessor macros,
0006  * with compile-time size and alignment, and accessors to the "rows" and "columns".
0007  */
0008 
0009 #include "FWCore/Reflection/interface/reflex.h"
0010 
0011 #include "SoACommon.h"
0012 
0013 /* dump SoA fields information; these should expand to, for columns:
0014  * Example:
0015  * GENERATE_SOA_LAYOUT(SoA,
0016  *   // predefined static scalars
0017  *   // size_t size;
0018  *   // size_t alignment;
0019  *
0020  *   // columns: one value per element
0021  *   SOA_COLUMN(double, x),
0022  *   SOA_COLUMN(double, y),
0023  *   SOA_COLUMN(double, z),
0024  *   SOA_EIGEN_COLUMN(Eigen::Vector3d, a),
0025  *   SOA_EIGEN_COLUMN(Eigen::Vector3d, b),
0026  *   SOA_EIGEN_COLUMN(Eigen::Vector3d, r),
0027  *   SOA_COLUMN(uint16_t, colour),
0028  *   SOA_COLUMN(int32_t, value),
0029  *   SOA_COLUMN(double *, py),
0030  *   SOA_COLUMN(uint32_t, count),
0031  *   SOA_COLUMN(uint32_t, anotherCount),
0032  *
0033  *   // scalars: one value for the whole structure
0034  *   SOA_SCALAR(const char *, description), 
0035  *   SOA_SCALAR(uint32_t, someNumber)
0036  * );
0037  *
0038  * dumps as:
0039  * SoA(32, 64):
0040  *   sizeof(SoA): 152
0041  *  Column x_ at offset 0 has size 256 and padding 0
0042  *  Column y_ at offset 256 has size 256 and padding 0
0043  *  Column z_ at offset 512 has size 256 and padding 0
0044  *  Eigen value a_ at offset 768 has dimension (3 x 1) and per column size 256 and padding 0
0045  *  Eigen value b_ at offset 1536 has dimension (3 x 1) and per column size 256 and padding 0
0046  *  Eigen value r_ at offset 2304 has dimension (3 x 1) and per column size 256 and padding 0
0047  *  Column colour_ at offset 3072 has size 64 and padding 0
0048  *  Column value_ at offset 3136 has size 128 and padding 0
0049  *  Column py_ at offset 3264 has size 256 and padding 0
0050  *  Column count_ at offset 3520 has size 128 and padding 0
0051  *  Column anotherCount_ at offset 3648 has size 128 and padding 0
0052  *  Scalar description_ at offset 3776 has size 8 and padding 56
0053  *  Scalar someNumber_ at offset 3840 has size 4 and padding 60
0054  * Final offset = 3904 computeDataSize(...): 3904
0055  *
0056  */
0057 
0058 namespace cms::soa {
0059 
0060   /* Traits for the different column type scenarios */
0061   /* Value traits passes the class as is in the case of column type and return
0062    * an empty class with functions returning non-scalar as accessors. */
0063   template <class C, SoAColumnType COLUMN_TYPE>
0064   struct ConstValueTraits : public C {
0065     using C::C;
0066   };
0067 
0068   template <class C>
0069   struct ConstValueTraits<C, SoAColumnType::scalar> {
0070     // Just take to SoAValue type to generate the right constructor.
0071     SOA_HOST_DEVICE SOA_INLINE ConstValueTraits(size_type, const typename C::valueType*) {}
0072     SOA_HOST_DEVICE SOA_INLINE ConstValueTraits(size_type, const typename C::Params&) {}
0073     SOA_HOST_DEVICE SOA_INLINE ConstValueTraits(size_type, const typename C::ConstParams&) {}
0074     // Any attempt to do anything with the "scalar" value a const element will fail.
0075   };
0076 
0077   /* Helper to extract the column type from a ConstValue type
0078    * and so to avoid commas inside macros. */
0079   template <typename C>
0080   struct ColumnTypeOf;
0081 
0082   template <SoAColumnType CT, typename T, byte_size_type ALIGNMENT, bool RESTRICT>
0083   struct ColumnTypeOf<SoAConstValue<CT, T, ALIGNMENT, RESTRICT>> {
0084     static constexpr SoAColumnType value = CT;
0085   };
0086 
0087   template <typename C>
0088   using ConstValueTraitsFromC = cms::soa::ConstValueTraits<C, ColumnTypeOf<C>::value>;
0089 }  // namespace cms::soa
0090 // namespace cms::soa
0091 
0092 // -------- MACROS FOR GENERATING SOA LAYOUT --------
0093 
0094 #define _COUNT_SOA_METHODS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS, DATA) \
0095   BOOST_PP_IF(BOOST_PP_EQUAL(VALUE_TYPE, _VALUE_TYPE_METHOD), DATA++;, BOOST_PP_EMPTY())
0096 
0097 #define _COUNT_SOA_METHODS(R, DATA, TYPE_NAME) \
0098   BOOST_PP_EXPAND(_COUNT_SOA_METHODS_IMPL BOOST_PP_TUPLE_PUSH_BACK(TYPE_NAME, DATA))
0099 
0100 #define _COUNT_SOA_CONST_METHODS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS, DATA) \
0101   BOOST_PP_IF(BOOST_PP_EQUAL(VALUE_TYPE, _VALUE_TYPE_CONST_METHOD), DATA++;, BOOST_PP_EMPTY())
0102 
0103 #define _COUNT_SOA_CONST_METHODS(R, DATA, TYPE_NAME) \
0104   BOOST_PP_EXPAND(_COUNT_SOA_CONST_METHODS_IMPL BOOST_PP_TUPLE_PUSH_BACK(TYPE_NAME, DATA))
0105 
0106 // clang-format off
0107 #define _DECLARE_SOA_STREAM_INFO_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                                \
0108   _SWITCH_ON_TYPE(                                                                                                     \
0109       VALUE_TYPE,                                                                                                      \
0110       /* Dump scalar */                                                                                                \
0111       _soa_impl_os << " Scalar " BOOST_PP_STRINGIZE(NAME) " at offset " << _soa_impl_offset                            \
0112          << " has size " << sizeof(CPP_TYPE)                                                                           \
0113          << " and padding " << ((sizeof(CPP_TYPE) - 1) / alignment + 1) * alignment - sizeof(CPP_TYPE)                 \
0114          << std::endl;                                                                                                 \
0115       _soa_impl_offset += ((sizeof(CPP_TYPE) - 1) / alignment + 1) * alignment;                                        \
0116       ,                                                                                                                \
0117       /* Dump column */                                                                                                \
0118       _soa_impl_os << " Column " BOOST_PP_STRINGIZE(NAME) " at offset " << _soa_impl_offset << " has size "            \
0119          << sizeof(CPP_TYPE) * elements_ << " and padding "                                                            \
0120          << cms::soa::alignSize(elements_ * sizeof(CPP_TYPE), alignment) - (elements_ * sizeof(CPP_TYPE))              \
0121          << std::endl;                                                                                                 \
0122       _soa_impl_offset += cms::soa::alignSize(elements_ * sizeof(CPP_TYPE), alignment);                                \
0123       ,                                                                                                                \
0124       /* Dump Eigen column */                                                                                          \
0125       _soa_impl_os << " Eigen value " BOOST_PP_STRINGIZE(NAME) " at offset " << _soa_impl_offset << " has dimension "  \
0126          << "(" << CPP_TYPE::RowsAtCompileTime << " x " << CPP_TYPE::ColsAtCompileTime << ")"                          \
0127          << " and per column size "                                                                                    \
0128          << sizeof(CPP_TYPE::Scalar) * elements_                                                                       \
0129          << " and padding "                                                                                            \
0130          << cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)                                       \
0131             - (elements_ * sizeof(CPP_TYPE::Scalar))                                                                   \
0132          << std::endl;                                                                                                 \
0133       _soa_impl_offset += cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)                         \
0134                 * CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                           \
0135   )
0136 // clang-format on
0137 
0138 #define _DECLARE_SOA_STREAM_INFO(R, DATA, TYPE_NAME)                                        \
0139   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0140               BOOST_PP_EMPTY(),                                                             \
0141               BOOST_PP_EXPAND(_DECLARE_SOA_STREAM_INFO_IMPL TYPE_NAME))
0142 
0143 /**
0144  * Metadata member computing column pitch
0145  */
0146 // clang-format off
0147 #define _DEFINE_METADATA_MEMBERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                                \
0148   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0149       /* Scalar */                                                                                                     \
0150       byte_size_type BOOST_PP_CAT(NAME, Pitch()) const {                                                               \
0151         return cms::soa::alignSize(sizeof(CPP_TYPE), ParentClass::alignment);                                          \
0152       }                                                                                                                \
0153       constexpr static cms::soa::SoAColumnType BOOST_PP_CAT(ColumnTypeOf_, NAME) = cms::soa::SoAColumnType::scalar;    \
0154       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0155       CPP_TYPE const* BOOST_PP_CAT(addressOf_, NAME)() const {                                                         \
0156         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0157       }                                                                                                                \
0158       using BOOST_PP_CAT(ParametersTypeOf_, NAME) =                                                                    \
0159         cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::scalar>::DataType<CPP_TYPE>;                       \
0160       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0161       BOOST_PP_CAT(ParametersTypeOf_, NAME) BOOST_PP_CAT(parametersOf_, NAME)() const {                                \
0162         return  BOOST_PP_CAT(ParametersTypeOf_, NAME) (parent_.BOOST_PP_CAT(NAME, _));                                 \
0163       }                                                                                                                \
0164       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0165       CPP_TYPE* BOOST_PP_CAT(addressOf_, NAME)() {                                                                     \
0166         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0167       },                                                                                                               \
0168       /* Column */                                                                                                     \
0169       using BOOST_PP_CAT(ParametersTypeOf_, NAME) =                                                                    \
0170         cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::column>::DataType<CPP_TYPE>;                       \
0171       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0172       BOOST_PP_CAT(ParametersTypeOf_, NAME) BOOST_PP_CAT(parametersOf_, NAME)() const {                                \
0173         return  BOOST_PP_CAT(ParametersTypeOf_, NAME) (parent_.BOOST_PP_CAT(NAME, _));                                 \
0174       }                                                                                                                \
0175       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0176       CPP_TYPE const* BOOST_PP_CAT(addressOf_, NAME)() const {                                                         \
0177         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0178       }                                                                                                                \
0179       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0180       CPP_TYPE* BOOST_PP_CAT(addressOf_, NAME)() {                                                                     \
0181         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0182       }                                                                                                                \
0183       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0184       byte_size_type BOOST_PP_CAT(NAME, Pitch()) const {                                                               \
0185         return cms::soa::alignSize(parent_.elements_ * sizeof(CPP_TYPE), ParentClass::alignment);                      \
0186       }                                                                                                                \
0187       constexpr static cms::soa::SoAColumnType BOOST_PP_CAT(ColumnTypeOf_, NAME) = cms::soa::SoAColumnType::column;,   \
0188       /* Eigen column */                                                                                               \
0189       using BOOST_PP_CAT(ParametersTypeOf_, NAME) =                                                                    \
0190           cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::eigen>::DataType<CPP_TYPE>;                      \
0191       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0192       BOOST_PP_CAT(ParametersTypeOf_, NAME) BOOST_PP_CAT(parametersOf_, NAME)() const {                                \
0193         return BOOST_PP_CAT(ParametersTypeOf_, NAME) (                                                                 \
0194           parent_.BOOST_PP_CAT(NAME, _),                                                                               \
0195           parent_.BOOST_PP_CAT(NAME, Stride_));                                                                        \
0196       }                                                                                                                \
0197       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0198       byte_size_type BOOST_PP_CAT(NAME, Pitch()) const {                                                               \
0199         return cms::soa::alignSize(parent_.elements_ * sizeof(CPP_TYPE::Scalar), ParentClass::alignment)               \
0200               * CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                             \
0201       }                                                                                                                \
0202       constexpr static cms::soa::SoAColumnType BOOST_PP_CAT(ColumnTypeOf_, NAME) = cms::soa::SoAColumnType::eigen;     \
0203       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0204       CPP_TYPE::Scalar const* BOOST_PP_CAT(addressOf_, NAME)() const {                                                 \
0205         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0206       }                                                                                                                \
0207       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0208       CPP_TYPE::Scalar* BOOST_PP_CAT(addressOf_, NAME)() {                                                             \
0209         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0210       }                                                                                                                \
0211   )
0212 // clang-format on
0213 
0214 #define _DEFINE_METADATA_MEMBERS(R, DATA, TYPE_NAME)                                        \
0215   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0216               BOOST_PP_EMPTY(),                                                             \
0217               BOOST_PP_EXPAND(_DEFINE_METADATA_MEMBERS_IMPL TYPE_NAME))
0218 
0219 /**
0220  * Declare the spans of the const descriptor data member 
0221  */
0222 // clang-format off
0223 #define _DECLARE_CONST_DESCRIPTOR_SPANS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                        \
0224   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                         \
0225     /* Scalar */                                                                                                      \
0226     (std::span<std::add_const_t<CPP_TYPE>>)                                                                           \
0227     ,                                                                                                                 \
0228     /* Column */                                                                                                      \
0229     (std::span<std::add_const_t<CPP_TYPE>>)                                                                           \
0230     ,                                                                                                                 \
0231     /* Eigen column*/                                                                                                 \
0232     (std::span<std::add_const_t<CPP_TYPE::Scalar>>)                                                                   \
0233   )
0234 // clang-format on
0235 
0236 #define _DECLARE_CONST_DESCRIPTOR_SPANS(R, DATA, TYPE_NAME)                                 \
0237   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0238               BOOST_PP_EMPTY(),                                                             \
0239               BOOST_PP_EXPAND(_DECLARE_CONST_DESCRIPTOR_SPANS_IMPL TYPE_NAME))
0240 
0241 /**
0242  * Declare the spans of the descriptor data member 
0243  */
0244 // clang-format off
0245 #define _DECLARE_DESCRIPTOR_SPANS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                              \
0246   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                         \
0247     /* Scalar */                                                                                                      \
0248     (std::span<CPP_TYPE>)                                                                                             \
0249     ,                                                                                                                 \
0250     /* Column */                                                                                                      \
0251     (std::span<CPP_TYPE>)                                                                                             \
0252     ,                                                                                                                 \
0253     /* Eigen column */                                                                                                \
0254     (std::span<CPP_TYPE::Scalar>)                                                                                     \
0255   )
0256 // clang-format on
0257 
0258 #define _DECLARE_DESCRIPTOR_SPANS(R, DATA, TYPE_NAME)                                       \
0259   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0260               BOOST_PP_EMPTY(),                                                             \
0261               BOOST_PP_EXPAND(_DECLARE_DESCRIPTOR_SPANS_IMPL TYPE_NAME))
0262 
0263 /**
0264  * Build the spans of the (const) descriptor from a (const) view 
0265  */
0266 // clang-format off
0267 #define _ASSIGN_SPAN_TO_COLUMNS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                                \
0268   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                         \
0269     /* Scalar */                                                                                                      \
0270     (std::span(view.metadata().BOOST_PP_CAT(addressOf_, NAME)(),                                                      \
0271                     cms::soa::alignSize(sizeof(CPP_TYPE), alignment) / sizeof(CPP_TYPE)))                             \
0272     ,                                                                                                                 \
0273     /* Column */                                                                                                      \
0274     (std::span(view.metadata().BOOST_PP_CAT(addressOf_, NAME)(),                                                      \
0275                     cms::soa::alignSize(view.metadata().size() * sizeof(CPP_TYPE), alignment) / sizeof(CPP_TYPE)))    \
0276     ,                                                                                                                 \
0277     /* Eigen column */                                                                                                \
0278     (std::span(view.metadata().BOOST_PP_CAT(addressOf_, NAME)(),                                                      \
0279                     cms::soa::alignSize(view.metadata().size() * sizeof(CPP_TYPE::Scalar), alignment) *               \
0280                         CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime / sizeof(CPP_TYPE::Scalar)))        \
0281   )
0282 // clang-format on
0283 
0284 #define _ASSIGN_SPAN_TO_COLUMNS(R, DATA, TYPE_NAME)                                         \
0285   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0286               BOOST_PP_EMPTY(),                                                             \
0287               BOOST_PP_EXPAND(_ASSIGN_SPAN_TO_COLUMNS_IMPL TYPE_NAME))
0288 
0289 // clang-format off
0290 #define _DECLARE_MEMBER_TRIVIAL_CONSTRUCTION_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                    \
0291   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0292       /* Scalar */                                                                                                     \
0293       (BOOST_PP_CAT(NAME, _)(nullptr)),                                                                                \
0294       /* Column */                                                                                                     \
0295       (BOOST_PP_CAT(NAME, _)(nullptr)),                                                                                \
0296       /* Eigen column */                                                                                               \
0297       (BOOST_PP_CAT(NAME, ElementsWithPadding_)(0))                                                                    \
0298       (BOOST_PP_CAT(NAME, _)(nullptr))                                                                                 \
0299       (BOOST_PP_CAT(NAME, Stride_)(0))                                                                                 \
0300 )
0301 // clang-format on
0302 
0303 #define _DECLARE_MEMBER_TRIVIAL_CONSTRUCTION(R, DATA, TYPE_NAME)                            \
0304   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0305               BOOST_PP_EMPTY(),                                                             \
0306               BOOST_PP_EXPAND(_DECLARE_MEMBER_TRIVIAL_CONSTRUCTION_IMPL TYPE_NAME))
0307 
0308 // clang-format off
0309 #define _DECLARE_MEMBER_COPY_CONSTRUCTION_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                       \
0310   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0311       /* Scalar */                                                                                                     \
0312       (BOOST_PP_CAT(NAME, _){_soa_impl_other.BOOST_PP_CAT(NAME, _)}),                                                  \
0313       /* Column */                                                                                                     \
0314       (BOOST_PP_CAT(NAME, _){_soa_impl_other.BOOST_PP_CAT(NAME, _)}),                                                  \
0315       /* Eigen column */                                                                                               \
0316       (BOOST_PP_CAT(NAME, ElementsWithPadding_){_soa_impl_other.BOOST_PP_CAT(NAME, ElementsWithPadding_)})             \
0317       (BOOST_PP_CAT(NAME, _){_soa_impl_other.BOOST_PP_CAT(NAME, _)})                                                   \
0318       (BOOST_PP_CAT(NAME, Stride_){_soa_impl_other.BOOST_PP_CAT(NAME, Stride_)})                                       \
0319   )
0320 // clang-format on
0321 
0322 #define _DECLARE_MEMBER_COPY_CONSTRUCTION(R, DATA, TYPE_NAME)                               \
0323   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0324               BOOST_PP_EMPTY(),                                                             \
0325               BOOST_PP_EXPAND(_DECLARE_MEMBER_COPY_CONSTRUCTION_IMPL TYPE_NAME))
0326 
0327 // clang-format off
0328 #define _DECLARE_MEMBER_ASSIGNMENT_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                              \
0329   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0330       /* Scalar */                                                                                                     \
0331       BOOST_PP_CAT(NAME, _) = _soa_impl_other.BOOST_PP_CAT(NAME, _);,                                                  \
0332       /* Column */                                                                                                     \
0333       BOOST_PP_CAT(NAME, _) = _soa_impl_other.BOOST_PP_CAT(NAME, _);,                                                  \
0334       /* Eigen column */                                                                                               \
0335       BOOST_PP_CAT(NAME, ElementsWithPadding_) = _soa_impl_other.BOOST_PP_CAT(NAME, ElementsWithPadding_);             \
0336       BOOST_PP_CAT(NAME, _) = _soa_impl_other.BOOST_PP_CAT(NAME, _);                                                   \
0337       BOOST_PP_CAT(NAME, Stride_) = _soa_impl_other.BOOST_PP_CAT(NAME, Stride_);                                       \
0338   )
0339 // clang-format on
0340 
0341 #define _DECLARE_MEMBER_ASSIGNMENT(R, DATA, TYPE_NAME)                                      \
0342   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0343               BOOST_PP_EMPTY(),                                                             \
0344               BOOST_PP_EXPAND(_DECLARE_MEMBER_ASSIGNMENT_IMPL TYPE_NAME))
0345 
0346 /**
0347  * Declare the value_element data members
0348  */
0349 // clang-format off
0350 #define _DEFINE_VALUE_ELEMENT_MEMBERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                           \
0351   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0352       /* Scalar (empty) */                                                                                             \
0353       ,                                                                                                                \
0354       /* Column */                                                                                                     \
0355       CPP_TYPE NAME;                                                                                                   \
0356       ,                                                                                                                \
0357       /* Eigen column */                                                                                               \
0358       CPP_TYPE NAME;                                                                                                   \
0359   )
0360 // clang-format on
0361 
0362 #define _DEFINE_VALUE_ELEMENT_MEMBERS(R, DATA, TYPE_NAME)                                   \
0363   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0364               BOOST_PP_EMPTY(),                                                             \
0365               BOOST_PP_EXPAND(_DEFINE_VALUE_ELEMENT_MEMBERS_IMPL TYPE_NAME))
0366 
0367 /**
0368  * List of data members in the value_element constructor arguments
0369  */
0370 // clang-format off
0371 #define _VALUE_ELEMENT_CTOR_ARGS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                                \
0372   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0373       /* Scalar (empty) */                                                                                             \
0374       ,                                                                                                                \
0375       /* Column */                                                                                                     \
0376       (CPP_TYPE NAME)                                                                                                  \
0377       ,                                                                                                                \
0378       /* Eigen column */                                                                                               \
0379       (CPP_TYPE NAME)                                                                                                  \
0380   )
0381 // clang-format on
0382 
0383 #define _VALUE_ELEMENT_CTOR_ARGS(R, DATA, TYPE_NAME)                                        \
0384   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0385               BOOST_PP_EMPTY(),                                                             \
0386               BOOST_PP_EXPAND(_VALUE_ELEMENT_CTOR_ARGS_IMPL TYPE_NAME))
0387 
0388 /**
0389  * List-initalise the value_element data members
0390  */
0391 // clang-format off
0392 #define _VALUE_ELEMENT_INITIALIZERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                             \
0393   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0394       /* Scalar (empty) */                                                                                             \
0395       ,                                                                                                                \
0396       /* Column */                                                                                                     \
0397       (NAME{NAME})                                                                                                     \
0398       ,                                                                                                                \
0399       /* Eigen column */                                                                                               \
0400       (NAME{NAME})                                                                                                     \
0401   )
0402 // clang-format on
0403 
0404 #define _VALUE_ELEMENT_INITIALIZERS(R, DATA, TYPE_NAME)                                     \
0405   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0406               BOOST_PP_EMPTY(),                                                             \
0407               BOOST_PP_EXPAND(_VALUE_ELEMENT_INITIALIZERS_IMPL TYPE_NAME))
0408 
0409 /**
0410  * Freeing of the ROOT-allocated column or scalar buffer
0411  */
0412 #define _ROOT_FREE_SOA_COLUMN_OR_SCALAR_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0413   delete[] BOOST_PP_CAT(NAME, _);                                              \
0414   BOOST_PP_CAT(NAME, _) = nullptr;
0415 
0416 #define _ROOT_FREE_SOA_COLUMN_OR_SCALAR(R, DATA, TYPE_NAME)                                 \
0417   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0418               BOOST_PP_EMPTY(),                                                             \
0419               BOOST_PP_EXPAND(_ROOT_FREE_SOA_COLUMN_OR_SCALAR_IMPL TYPE_NAME))
0420 
0421 /**
0422  * Computation of the column or scalar pointer location in the memory layout (at SoA construction time)
0423  */
0424 // clang-format off
0425 #define _ASSIGN_SOA_COLUMN_OR_SCALAR_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                            \
0426   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0427       /* Scalar */                                                                                                     \
0428       BOOST_PP_CAT(NAME, _) = reinterpret_cast<CPP_TYPE*>(_soa_impl_curMem);                                           \
0429       _soa_impl_curMem += cms::soa::alignSize(sizeof(CPP_TYPE), alignment);                                            \
0430       ,                                                                                                                \
0431       /* Column */                                                                                                     \
0432       BOOST_PP_CAT(NAME, _) = reinterpret_cast<CPP_TYPE*>(_soa_impl_curMem);                                           \
0433       _soa_impl_curMem += cms::soa::alignSize(elements_ * sizeof(CPP_TYPE), alignment);                                \
0434       ,                                                                                                                \
0435       /* Eigen column */                                                                                               \
0436       BOOST_PP_CAT(NAME, Stride_) = cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)               \
0437         / sizeof(CPP_TYPE::Scalar);                                                                                    \
0438       BOOST_PP_CAT(NAME, ElementsWithPadding_) = BOOST_PP_CAT(NAME, Stride_)                                           \
0439         *  CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                                  \
0440       BOOST_PP_CAT(NAME, _) = reinterpret_cast<CPP_TYPE::Scalar*>(_soa_impl_curMem);                                   \
0441       _soa_impl_curMem += cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)                         \
0442         * CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                                   \
0443   )                                                                                                                    \
0444   if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                                \
0445     if (reinterpret_cast<intptr_t>(BOOST_PP_CAT(NAME, _)) % alignment)                                                 \
0446       throw std::runtime_error("In layout constructor: misaligned column: " #NAME);
0447 // clang-format on
0448 
0449 #define _ASSIGN_SOA_COLUMN_OR_SCALAR(R, DATA, TYPE_NAME)                                    \
0450   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0451               BOOST_PP_EMPTY(),                                                             \
0452               BOOST_PP_EXPAND(_ASSIGN_SOA_COLUMN_OR_SCALAR_IMPL TYPE_NAME))
0453 
0454 /**
0455  * Computation of the column or scalar size for SoA size computation
0456  */
0457 // clang-format off
0458 #define _ACCUMULATE_SOA_ELEMENT_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                                 \
0459   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0460       /* Scalar */                                                                                                     \
0461       _soa_impl_ret += cms::soa::alignSize(sizeof(CPP_TYPE), alignment);                                               \
0462       ,                                                                                                                \
0463       /* Column */                                                                                                     \
0464       _soa_impl_ret += cms::soa::alignSize(elements * sizeof(CPP_TYPE), alignment);                                    \
0465       ,                                                                                                                \
0466       /* Eigen column */                                                                                               \
0467       _soa_impl_ret += cms::soa::alignSize(elements * sizeof(CPP_TYPE::Scalar), alignment)                             \
0468              * CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                              \
0469   )
0470 // clang-format on
0471 
0472 #define _ACCUMULATE_SOA_ELEMENT(R, DATA, TYPE_NAME)                                         \
0473   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0474               BOOST_PP_EMPTY(),                                                             \
0475               BOOST_PP_EXPAND(_ACCUMULATE_SOA_ELEMENT_IMPL TYPE_NAME))
0476 
0477 /**
0478  * Direct access to column pointer and indexed access
0479  */
0480 // clang-format off
0481 #define _DECLARE_SOA_ACCESSOR_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                                   \
0482   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0483       /* Scalar */                                                                                                     \
0484       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE& NAME() { return *BOOST_PP_CAT(NAME, _); }                                   \
0485       ,                                                                                                                \
0486       /* Column */                                                                                                     \
0487       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE* NAME() { return BOOST_PP_CAT(NAME, _); }                                    \
0488       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE& NAME(size_type _soa_impl_index) {                                           \
0489         return BOOST_PP_CAT(NAME, _)[_soa_impl_index];                                                                 \
0490       }                                                                                                                \
0491       ,                                                                                                                \
0492       /* Eigen column */                                                                                               \
0493       /* TODO: implement*/                                                                                             \
0494       BOOST_PP_EMPTY()                                                                                                 \
0495   )
0496 // clang-format on
0497 
0498 #define _DECLARE_SOA_ACCESSOR(R, DATA, TYPE_NAME)                                           \
0499   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0500               BOOST_PP_EMPTY(),                                                             \
0501               BOOST_PP_EXPAND(_DECLARE_SOA_ACCESSOR_IMPL TYPE_NAME))
0502 
0503 /**
0504  * Direct access to column pointer (const) and indexed access.
0505  */
0506 // clang-format off
0507 #define _DECLARE_SOA_CONST_ACCESSOR_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                             \
0508   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0509       /* Scalar */                                                                                                     \
0510       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE NAME() const { return *(BOOST_PP_CAT(NAME, _)); }                            \
0511       ,                                                                                                                \
0512       /* Column */                                                                                                     \
0513       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE const* NAME() const { return BOOST_PP_CAT(NAME, _); }                        \
0514       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE NAME(size_type _soa_impl_index) const {                                      \
0515         return *(BOOST_PP_CAT(NAME, _) + _soa_impl_index);                                                             \
0516       }                                                                                                                \
0517       ,                                                                                                                \
0518       /* Eigen column */                                                                                               \
0519       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE::Scalar const* NAME() const { return BOOST_PP_CAT(NAME, _); }                \
0520       SOA_HOST_DEVICE SOA_INLINE size_type BOOST_PP_CAT(NAME, Stride)() { return BOOST_PP_CAT(NAME, Stride_); }        \
0521   )
0522 // clang-format on
0523 
0524 #define _DECLARE_SOA_CONST_ACCESSOR(R, DATA, TYPE_NAME)                                     \
0525   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0526               BOOST_PP_EMPTY(),                                                             \
0527               BOOST_PP_EXPAND(_DECLARE_SOA_CONST_ACCESSOR_IMPL TYPE_NAME))
0528 
0529 /**
0530  * SoA member ROOT streamer read (column pointers).
0531  */
0532 // clang-format off
0533 #define _STREAMER_READ_SOA_DATA_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                          \
0534   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0535       /* Scalar */                                                                                                     \
0536       memcpy(BOOST_PP_CAT(NAME, _), onfile.BOOST_PP_CAT(NAME, _), sizeof(CPP_TYPE));                                   \
0537       ,                                                                                                                \
0538       /* Column */                                                                                                     \
0539       memcpy(BOOST_PP_CAT(NAME, _), onfile.BOOST_PP_CAT(NAME, _), sizeof(CPP_TYPE) * onfile.elements_);                \
0540       ,                                                                                                                \
0541       /* Eigen column */                                                                                               \
0542       memcpy(BOOST_PP_CAT(NAME, _), onfile.BOOST_PP_CAT(NAME, _),                                                      \
0543         sizeof(CPP_TYPE::Scalar) * BOOST_PP_CAT(NAME, ElementsWithPadding_));                                          \
0544   )
0545 // clang-format on
0546 
0547 #define _STREAMER_READ_SOA_DATA_MEMBER(R, DATA, TYPE_NAME)                                  \
0548   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0549               BOOST_PP_EMPTY(),                                                             \
0550               BOOST_PP_EXPAND(_STREAMER_READ_SOA_DATA_MEMBER_IMPL TYPE_NAME))
0551 
0552 // clang-format off
0553 #define _DECLARE_SOA_DATA_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0554 _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                            \
0555   /* Scalar */                                                                                                         \
0556   CPP_TYPE* BOOST_PP_CAT(NAME, _) EDM_REFLEX_SIZE(scalar_) = nullptr;                                                  \
0557   ,                                                                                                                    \
0558   /* Column */                                                                                                         \
0559   CPP_TYPE * BOOST_PP_CAT(NAME, _) EDM_REFLEX_SIZE(elements_) = nullptr;                                               \
0560   ,                                                                                                                    \
0561   /* Eigen column */                                                                                                   \
0562   size_type BOOST_PP_CAT(NAME, ElementsWithPadding_) = 0; /* For ROOT serialization */                                 \
0563   CPP_TYPE::Scalar * BOOST_PP_CAT(NAME, _) EDM_REFLEX_SIZE(BOOST_PP_CAT(NAME, ElementsWithPadding_)) = nullptr;        \
0564   byte_size_type BOOST_PP_CAT(NAME, Stride_) = 0;                                                                      \
0565 )
0566 // clang-format on
0567 
0568 #define _DECLARE_SOA_DATA_MEMBER(R, DATA, TYPE_NAME)                                        \
0569   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0570               BOOST_PP_EMPTY(),                                                             \
0571               BOOST_PP_EXPAND(_DECLARE_SOA_DATA_MEMBER_IMPL TYPE_NAME))
0572 
0573 // clang-format off
0574 #define _COPY_VIEW_COLUMNS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)           \
0575   _SWITCH_ON_TYPE(VALUE_TYPE, /* Scalar */                                  \
0576                   memcpy(BOOST_PP_CAT(this->metadata().addressOf_, NAME)(), \
0577                          BOOST_PP_CAT(view.metadata().addressOf_, NAME)(),  \
0578                          sizeof(CPP_TYPE));                                 \
0579                   , /* Column */                                            \
0580                   memcpy(BOOST_PP_CAT(this->metadata().addressOf_, NAME)(), \
0581                          BOOST_PP_CAT(view.metadata().addressOf_, NAME)(),  \
0582                          view.metadata().size() * sizeof(CPP_TYPE));        \
0583                   , /* Eigen column */                                      \
0584                   memcpy(BOOST_PP_CAT(this->metadata().addressOf_, NAME)(), \
0585                          BOOST_PP_CAT(view.metadata().addressOf_, NAME)(),  \
0586                          BOOST_PP_CAT(NAME, ElementsWithPadding_) * sizeof(CPP_TYPE::Scalar));)
0587 // clang-format on
0588 
0589 #define _COPY_VIEW_COLUMNS(R, DATA, TYPE_NAME)                                              \
0590   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0591               BOOST_PP_EMPTY(),                                                             \
0592               BOOST_PP_EXPAND(_COPY_VIEW_COLUMNS_IMPL TYPE_NAME))
0593 
0594 // -------- MACROS FOR GENERATING SOA VIEWS --------
0595 
0596 /**
0597  * Member types aliasing for referencing by name
0598  */
0599 // clang-format off
0600 #define _DECLARE_VIEW_MEMBER_TYPE_ALIAS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS, CAST)                                   \
0601   using BOOST_PP_CAT(ParametersTypeOf_, NAME) =                                                                        \
0602       typename TypeOf_Layout::Metadata::BOOST_PP_CAT(ParametersTypeOf_, NAME);                                         \
0603   using BOOST_PP_CAT(TypeOf_, NAME) = CPP_TYPE;                                                                        \
0604   constexpr static cms::soa::SoAColumnType BOOST_PP_CAT(ColumnTypeOf_, NAME) =                                         \
0605       TypeOf_Layout::Metadata::BOOST_PP_CAT(ColumnTypeOf_, NAME);                                                      \
0606   SOA_HOST_DEVICE SOA_INLINE                                                                                           \
0607   const auto BOOST_PP_CAT(parametersOf_, NAME)() const {                                                               \
0608     return CAST(parent_.BOOST_PP_CAT(NAME, Parameters_));                                                              \
0609   };
0610 // clang-format on
0611 
0612 // DATA should be a function used to convert
0613 //   parent_.LOCAL_NAME ## Parameters_
0614 // to
0615 //   ParametersTypeOf_ ## LOCAL_NAME                (for a View)
0616 // or
0617 //   ParametersTypeOf_ ## LOCAL_NAME :: ConstType   (for a ConstView)
0618 // or empty, if no conversion is necessary.
0619 #define _DECLARE_VIEW_MEMBER_TYPE_ALIAS(R, DATA, TYPE_NAME)                                 \
0620   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0621               BOOST_PP_EMPTY(),                                                             \
0622               BOOST_PP_EXPAND(_DECLARE_VIEW_MEMBER_TYPE_ALIAS_IMPL BOOST_PP_TUPLE_PUSH_BACK(TYPE_NAME, DATA)))
0623 
0624 /**
0625  * Member type const pointers for referencing by name
0626  */
0627 #define _DECLARE_VIEW_MEMBER_CONST_POINTERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0628   SOA_HOST_DEVICE SOA_INLINE auto const* BOOST_PP_CAT(addressOf_, NAME)() const {  \
0629     return parent_.BOOST_PP_CAT(NAME, Parameters_).addr_;                          \
0630   };
0631 
0632 #define _DECLARE_VIEW_MEMBER_CONST_POINTERS(R, DATA, TYPE_NAME)                             \
0633   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0634               BOOST_PP_EMPTY(),                                                             \
0635               BOOST_PP_EXPAND(_DECLARE_VIEW_MEMBER_CONST_POINTERS_IMPL TYPE_NAME))
0636 
0637 /**
0638  * Assign the value of the records to the column parameters.
0639  */
0640 #define _STRUCT_ELEMENT_INITIALIZERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0641   (BOOST_PP_CAT(NAME, _){parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)()})
0642 
0643 #define _STRUCT_ELEMENT_INITIALIZERS(R, DATA, TYPE_NAME)                                    \
0644   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0645               BOOST_PP_EMPTY(),                                                             \
0646               BOOST_PP_EXPAND(_STRUCT_ELEMENT_INITIALIZERS_IMPL TYPE_NAME))
0647 
0648 /**
0649  * Generator of accessors for (const) view Metarecords subclass.
0650  */
0651 #define _CONST_ACCESSORS_STRUCT_MEMBERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                        \
0652   cms::soa::ConstTuple<typename Metadata::BOOST_PP_CAT(ParametersTypeOf_, NAME)>::Type NAME() const { \
0653     return std::make_tuple(BOOST_PP_CAT(NAME, _), parent_.elements_);                                 \
0654   }
0655 
0656 #define _CONST_ACCESSORS_STRUCT_MEMBERS(R, DATA, TYPE_NAME)                                 \
0657   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0658               BOOST_PP_EMPTY(),                                                             \
0659               BOOST_PP_EXPAND(_CONST_ACCESSORS_STRUCT_MEMBERS_IMPL TYPE_NAME))
0660 
0661 /**
0662  * Generator of members for (const) view Metarecords subclass.
0663  */
0664 #define _DECLARE_STRUCT_CONST_DATA_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0665   typename Metadata::BOOST_PP_CAT(ParametersTypeOf_, NAME)::ConstType BOOST_PP_CAT(NAME, _);
0666 
0667 #define _DECLARE_STRUCT_CONST_DATA_MEMBER(R, srcDATA, TYPE_NAME)                            \
0668   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0669               BOOST_PP_EMPTY(),                                                             \
0670               BOOST_PP_EXPAND(_DECLARE_STRUCT_CONST_DATA_MEMBER_IMPL TYPE_NAME))
0671 
0672 /**
0673  * Generator of member initialization from constructor.
0674  * We use a lambda with auto return type to handle multiple possible return types.
0675  */
0676 // clang-format off
0677 #define _DECLARE_VIEW_MEMBER_INITIALIZERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                       \
0678   (BOOST_PP_CAT(NAME, Parameters_)([&]() -> auto {                                                                     \
0679     auto params = layout.metadata().BOOST_PP_CAT(parametersOf_, NAME)();                                               \
0680     if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                              \
0681       if (reinterpret_cast<intptr_t>(params.addr_) % alignment)                                                        \
0682         throw std::runtime_error("In constructor by layout: misaligned column: " #NAME);                               \
0683     return params;                                                                                                     \
0684   }()))
0685 // clang-format on
0686 
0687 #define _DECLARE_VIEW_MEMBER_INITIALIZERS(R, DATA, TYPE_NAME)                               \
0688   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0689               BOOST_PP_EMPTY(),                                                             \
0690               BOOST_PP_EXPAND(_DECLARE_VIEW_MEMBER_INITIALIZERS_IMPL TYPE_NAME))
0691 
0692 /**
0693  * Generator of parameters for constructor by column.
0694  */
0695 #define _DECLARE_VIEW_CONSTRUCTION_BYCOLUMN_PARAMETERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS, DATA) \
0696   (typename BOOST_PP_CAT(Metadata::ParametersTypeOf_, NAME)::TupleOrPointerType NAME)
0697 
0698 #define _DECLARE_VIEW_CONSTRUCTION_BYCOLUMN_PARAMETERS(R, DATA, TYPE_NAME)          \
0699   BOOST_PP_IF(                                                                      \
0700       BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0701       BOOST_PP_EMPTY(),                                                             \
0702       BOOST_PP_EXPAND(_DECLARE_VIEW_CONSTRUCTION_BYCOLUMN_PARAMETERS_IMPL BOOST_PP_TUPLE_PUSH_BACK(TYPE_NAME, DATA)))
0703 
0704 /**
0705  * Generator of member initialization from constructor.
0706  * We use a lambda with auto return type to handle multiple possible return types.
0707  */
0708 // clang-format off
0709 #define _DECLARE_VIEW_MEMBER_INITIALIZERS_BYCOLUMN_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                              \
0710   (                                                                                                                    \
0711     BOOST_PP_CAT(NAME, Parameters_)([&]() -> auto {                                                                    \
0712       if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                            \
0713         if (Metadata:: BOOST_PP_CAT(ParametersTypeOf_, NAME)::checkAlignment(NAME, alignment))                         \
0714           throw std::runtime_error("In constructor by column: misaligned column: " #NAME);                             \
0715       return NAME;                                                                                                     \
0716     }())                                                                                                               \
0717   )
0718 // clang-format on
0719 
0720 #define _DECLARE_VIEW_MEMBER_INITIALIZERS_BYCOLUMN(R, DATA, TYPE_NAME)                      \
0721   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0722               BOOST_PP_EMPTY(),                                                             \
0723               BOOST_PP_EXPAND(_DECLARE_VIEW_MEMBER_INITIALIZERS_BYCOLUMN_IMPL TYPE_NAME))
0724 
0725 /**
0726  * Generator of parameters for (const) view Metarecords subclass.
0727  */
0728 #define _DECLARE_CONST_VIEW_CONSTRUCTOR_COLUMNS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0729   (cms::soa::ConstTuple<typename Metadata::BOOST_PP_CAT(ParametersTypeOf_, NAME)>::Type NAME)
0730 
0731 #define _DECLARE_CONST_VIEW_CONSTRUCTOR_COLUMNS(R, DATA, TYPE_NAME)                         \
0732   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0733               BOOST_PP_EMPTY(),                                                             \
0734               BOOST_PP_EXPAND(_DECLARE_CONST_VIEW_CONSTRUCTOR_COLUMNS_IMPL TYPE_NAME))
0735 
0736 // clang-format off
0737 #define _INITIALIZE_CONST_VIEW_PARAMETERS_AND_SIZE_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                              \
0738   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0739       /* Scalar */                                                                                                     \
0740         if (not readyToSet) {                                                                                          \
0741           elements_ = std::get<1>(NAME);                                                                               \
0742           readyToSet = true;                                                                                           \
0743         }                                                                                                              \
0744         BOOST_PP_CAT(NAME, Parameters_) = [&]() -> auto {                                                              \
0745           if (elements_ != std::get<1>(NAME))                                                                          \
0746             throw std::runtime_error(                                                                                  \
0747               "In constructor by column pointers: number of elements not equal for every column: "                     \
0748               BOOST_PP_STRINGIZE(NAME));                                                                               \
0749           if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                        \
0750             if (Metadata:: BOOST_PP_CAT(ParametersTypeOf_, NAME)::                                                     \
0751               checkAlignment(std::get<0>(NAME).tupleOrPointer(), alignment))                                           \
0752                 throw std::runtime_error("In constructor by column: misaligned column: " #NAME);                       \
0753           return std::get<0>(NAME);                                                                                    \
0754             }();                                                                                                       \
0755         ,                                                                                                              \
0756       /* Column */                                                                                                     \
0757         if (not readyToSet) {                                                                                          \
0758           elements_ = std::get<1>(NAME);                                                                               \
0759           readyToSet = true;                                                                                           \
0760         }                                                                                                              \
0761         BOOST_PP_CAT(NAME, Parameters_) = [&]() -> auto {                                                              \
0762           if (elements_ != std::get<1>(NAME))                                                                          \
0763             throw std::runtime_error(                                                                                  \
0764               "In constructor by column pointers: number of elements not equal for every column: "                     \
0765               BOOST_PP_STRINGIZE(NAME));                                                                               \
0766           if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                        \
0767             if (Metadata:: BOOST_PP_CAT(ParametersTypeOf_, NAME)::                                                     \
0768               checkAlignment(std::get<0>(NAME).tupleOrPointer(), alignment))                                           \
0769                 throw std::runtime_error("In constructor by column: misaligned column: " #NAME);                       \
0770           return std::get<0>(NAME);                                                                                    \
0771             }();                                                                                                       \
0772         ,                                                                                                              \
0773       /* Eigen column */                                                                                               \
0774         if (not readyToSet) {                                                                                          \
0775           elements_ = std::get<1>(NAME);                                                                               \
0776           readyToSet = true;                                                                                           \
0777         }                                                                                                              \
0778         BOOST_PP_CAT(NAME, Parameters_) = [&]() -> auto {                                                              \
0779           if (cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)                                     \
0780                     / sizeof(CPP_TYPE::Scalar) != std::get<0>(NAME).stride_) {                                         \
0781             throw std::runtime_error(                                                                                  \
0782               "In constructor by column pointers: stride not equal between eigen columns: "                            \
0783               BOOST_PP_STRINGIZE(NAME));                                                                               \
0784           }                                                                                                            \
0785           if (elements_ != std::get<1>(NAME))                                                                          \
0786           throw std::runtime_error(                                                                                    \
0787             "In constructor by column pointers: number of elements not equal for every column: "                       \
0788             BOOST_PP_STRINGIZE(NAME));                                                                                 \
0789           if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                        \
0790             if (Metadata:: BOOST_PP_CAT(ParametersTypeOf_, NAME)::                                                     \
0791               checkAlignment(std::get<0>(NAME).tupleOrPointer(), alignment))                                           \
0792                 throw std::runtime_error("In constructor by column: misaligned column: " #NAME);                       \
0793           return std::get<0>(NAME);                                                                                    \
0794           }();                                                                                                         \
0795   )
0796 // clang-format on
0797 
0798 #define _INITIALIZE_CONST_VIEW_PARAMETERS_AND_SIZE(R, DATA, TYPE_NAME)                      \
0799   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0800               BOOST_PP_EMPTY(),                                                             \
0801               BOOST_PP_EXPAND(_INITIALIZE_CONST_VIEW_PARAMETERS_AND_SIZE_IMPL TYPE_NAME))
0802 
0803 /**
0804  * Generator of view member list.
0805  */
0806 #define _DECLARE_VIEW_OTHER_MEMBER_LIST_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0807   (cms::soa::const_cast_SoAParametersImpl(other.BOOST_PP_CAT(NAME, Parameters_)).tupleOrPointer())
0808 
0809 #define _DECLARE_VIEW_OTHER_MEMBER_LIST(R, DATA, TYPE_NAME)                                 \
0810   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0811               BOOST_PP_EMPTY(),                                                             \
0812               BOOST_PP_EXPAND(_DECLARE_VIEW_OTHER_MEMBER_LIST_IMPL TYPE_NAME))
0813 
0814 /**
0815  * Generator of parameters for (const) element subclass (expanded comma separated).
0816  */
0817 #define _DECLARE_CONST_VIEW_ELEMENT_VALUE_ARG_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0818   (const typename BOOST_PP_CAT(Metadata::ParametersTypeOf_, NAME)::ConstType NAME)
0819 
0820 #define _DECLARE_CONST_VIEW_ELEMENT_VALUE_ARG(R, DATA, TYPE_NAME)                           \
0821   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0822               BOOST_PP_EMPTY(),                                                             \
0823               BOOST_PP_EXPAND(_DECLARE_CONST_VIEW_ELEMENT_VALUE_ARG_IMPL TYPE_NAME))
0824 
0825 /**
0826  * Generator of member initialization for constructor of element subclass
0827  */
0828 #define _DECLARE_VIEW_CONST_ELEM_MEMBER_INIT_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS, DATA) \
0829   (BOOST_PP_CAT(NAME, _)(DATA, NAME))
0830 
0831 /* declare AoS-like element value args for contructor; these should expand,for columns only */
0832 #define _DECLARE_VIEW_CONST_ELEM_MEMBER_INIT(R, DATA, TYPE_NAME)                            \
0833   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0834               BOOST_PP_EMPTY(),                                                             \
0835               BOOST_PP_EXPAND(_DECLARE_VIEW_CONST_ELEM_MEMBER_INIT_IMPL BOOST_PP_TUPLE_PUSH_BACK(TYPE_NAME, DATA)))
0836 
0837 /**
0838  * Declaration of the members accessors of the const element subclass
0839  */
0840 // clang-format off
0841 #define _DECLARE_VIEW_CONST_ELEMENT_ACCESSOR_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                    \
0842   SOA_HOST_DEVICE SOA_INLINE                                                                                           \
0843       const typename cms::soa::SoAConstValue_ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template         \
0844               DataType<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::template                                       \
0845                   Alignment<conditionalAlignment>::template ConstValue<restrictQualify>::RefToConst                    \
0846       NAME() const {                                                                                                   \
0847     return BOOST_PP_CAT(NAME, _)();                                                                                    \
0848   }
0849 // clang-format on
0850 
0851 #define _DECLARE_VIEW_CONST_ELEMENT_ACCESSOR(R, DATA, TYPE_NAME)                            \
0852   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0853               BOOST_PP_EMPTY(),                                                             \
0854               _DECLARE_VIEW_CONST_ELEMENT_ACCESSOR_IMPL TYPE_NAME)
0855 
0856 /**
0857  * Declaration of the private members of the const element subclass
0858  */
0859 // clang-format off
0860 #define _DECLARE_VIEW_CONST_ELEMENT_VALUE_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                               \
0861   const cms::soa::ConstValueTraitsFromC<typename cms::soa::SoAConstValue_ColumnType<                                  \
0862       BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template                                                          \
0863           DataType<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::template                                          \
0864               Alignment<conditionalAlignment>::template ConstValue<restrictQualify>>                                  \
0865       BOOST_PP_CAT(NAME, _);
0866 // clang-format on
0867 
0868 #define _DECLARE_VIEW_CONST_ELEMENT_VALUE_MEMBER(R, DATA, TYPE_NAME)                        \
0869   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0870               BOOST_PP_EMPTY(),                                                             \
0871               BOOST_PP_EXPAND(_DECLARE_VIEW_CONST_ELEMENT_VALUE_MEMBER_IMPL TYPE_NAME))
0872 
0873 /**
0874  * Parameters passed to const element subclass constructor in operator[]
0875  */
0876 #define _DECLARE_VIEW_CONST_ELEMENT_CONSTR_CALL_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) (BOOST_PP_CAT(NAME, Parameters_))
0877 
0878 #define _DECLARE_VIEW_CONST_ELEMENT_CONSTR_CALL(R, DATA, TYPE_NAME)                         \
0879   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0880               BOOST_PP_EMPTY(),                                                             \
0881               BOOST_PP_EXPAND(_DECLARE_VIEW_CONST_ELEMENT_CONSTR_CALL_IMPL TYPE_NAME))
0882 
0883 /**
0884  * Direct access to column pointer (const) and indexed access.
0885  */
0886 // clang-format off
0887 #define _DECLARE_VIEW_SOA_CONST_ACCESSOR_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                       \
0888   /* Column or scalar */                                                                                              \
0889   SOA_HOST_DEVICE SOA_INLINE                                                                                          \
0890   typename cms::soa::SoAAccessors<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::                                   \
0891         template ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template AccessType<                        \
0892             cms::soa::SoAAccessType::constAccess>::template Alignment<conditionalAlignment>::                         \
0893                 template RestrictQualifier<restrictQualify>::NoParamReturnType                                        \
0894   NAME() const {                                                                                                      \
0895     return typename cms::soa::SoAAccessors<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::                          \
0896         template ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template AccessType<                        \
0897             cms::soa::SoAAccessType::constAccess>::template Alignment<conditionalAlignment>::                         \
0898                 template RestrictQualifier<restrictQualify>(BOOST_PP_CAT(NAME, Parameters_))();                       \
0899   }                                                                                                                   \
0900   SOA_HOST_DEVICE SOA_INLINE                                                                                          \
0901   typename cms::soa::SoAAccessors<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::                                   \
0902         template ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template AccessType<                        \
0903             cms::soa::SoAAccessType::constAccess>::template Alignment<conditionalAlignment>::                         \
0904                 template RestrictQualifier<restrictQualify>::ParamReturnType                                          \
0905   NAME(size_type _soa_impl_index) const {                                                                             \
0906     if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {                                                \
0907       if (_soa_impl_index >= elements_ or _soa_impl_index < 0)                                                        \
0908         SOA_THROW_OUT_OF_RANGE("Out of range index in const " #NAME "(size_type index)",                              \
0909           _soa_impl_index, elements_)                                                                                 \
0910     }                                                                                                                 \
0911     return typename cms::soa::SoAAccessors<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::                          \
0912         template ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template AccessType<                        \
0913             cms::soa::SoAAccessType::constAccess>::template Alignment<conditionalAlignment>::                         \
0914                 template RestrictQualifier<restrictQualify>(BOOST_PP_CAT(NAME, Parameters_))(_soa_impl_index);        \
0915   } \
0916   // clang-format on
0917 
0918 #define _DECLARE_VIEW_SOA_CONST_ACCESSOR(R, DATA, TYPE_NAME)                                \
0919   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0920               BOOST_PP_EMPTY(),                                                             \
0921               BOOST_PP_EXPAND(_DECLARE_VIEW_SOA_CONST_ACCESSOR_IMPL TYPE_NAME))
0922 
0923 /**
0924  * Const SoA class member declaration (column pointers and parameters).
0925  */
0926 #define _DECLARE_CONST_VIEW_SOA_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0927   typename BOOST_PP_CAT(Metadata::ParametersTypeOf_, NAME)::ConstType BOOST_PP_CAT(NAME, Parameters_);
0928 
0929 #define _DECLARE_CONST_VIEW_SOA_MEMBER(R, DATA, TYPE_NAME)                                  \
0930   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0931               BOOST_PP_EMPTY(),                                                             \
0932               BOOST_PP_EXPAND(_DECLARE_CONST_VIEW_SOA_MEMBER_IMPL TYPE_NAME))
0933 
0934 /**
0935  * Member type pointers for referencing by name
0936  */
0937 // clang-format off
0938 #define _DECLARE_VIEW_MEMBER_POINTERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                         \
0939   SOA_HOST_DEVICE SOA_INLINE auto* BOOST_PP_CAT(addressOf_, NAME)() {                                                \
0940     return BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                                                \
0941   };
0942 // clang-format on
0943 
0944 #define _DECLARE_VIEW_MEMBER_POINTERS(R, DATA, TYPE_NAME)                                   \
0945   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0946               BOOST_PP_EMPTY(),                                                             \
0947               BOOST_PP_EXPAND(_DECLARE_VIEW_MEMBER_POINTERS_IMPL TYPE_NAME))
0948 
0949 /**
0950  * Generator of accessors for (const) view Metarecords subclass.
0951  */
0952 #define _ACCESSORS_STRUCT_MEMBERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                         \
0953   cms::soa::Tuple<typename Metadata::BOOST_PP_CAT(ParametersTypeOf_, NAME)>::Type NAME() const { \
0954     return std::make_tuple(BOOST_PP_CAT(NAME, _), parent_.elements_);                            \
0955   }
0956 
0957 #define _ACCESSORS_STRUCT_MEMBERS(R, DATA, TYPE_NAME)                                       \
0958   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0959               BOOST_PP_EMPTY(),                                                             \
0960               BOOST_PP_EXPAND(_ACCESSORS_STRUCT_MEMBERS_IMPL TYPE_NAME))
0961 
0962 /**
0963  * Generator of members for view Metarecords subclass.
0964  */
0965 #define _DECLARE_STRUCT_DATA_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0966   typename Metadata::BOOST_PP_CAT(ParametersTypeOf_, NAME) BOOST_PP_CAT(NAME, _);
0967 
0968 #define _DECLARE_STRUCT_DATA_MEMBER(R, DATA, TYPE_NAME)                                     \
0969   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0970               BOOST_PP_EMPTY(),                                                             \
0971               BOOST_PP_EXPAND(_DECLARE_STRUCT_DATA_MEMBER_IMPL TYPE_NAME))
0972 
0973 /**
0974  * Generator of view member list.
0975  */
0976 #define _DECLARE_VIEW_MEMBER_LIST_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) (NAME)
0977 
0978 #define _DECLARE_VIEW_MEMBER_LIST(R, DATA, TYPE_NAME)                                       \
0979   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0980               BOOST_PP_EMPTY(),                                                             \
0981               BOOST_PP_EXPAND(_DECLARE_VIEW_MEMBER_LIST_IMPL TYPE_NAME))
0982 
0983 /**
0984  * Generator of parameters for view Metarecords subclass.
0985  */
0986 #define _DECLARE_VIEW_CONSTRUCTOR_COLUMNS_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
0987   (cms::soa::Tuple<typename Metadata::BOOST_PP_CAT(ParametersTypeOf_, NAME)>::Type NAME)
0988 
0989 #define _DECLARE_VIEW_CONSTRUCTOR_COLUMNS(R, DATA, TYPE_NAME)                               \
0990   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
0991               BOOST_PP_EMPTY(),                                                             \
0992               BOOST_PP_EXPAND(_DECLARE_VIEW_CONSTRUCTOR_COLUMNS_IMPL TYPE_NAME))
0993 
0994 // clang-format off
0995 #define _INITIALIZE_VIEW_PARAMETERS_AND_SIZE_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                  \
0996 _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0997     /* Scalar */                                                                                                     \
0998       if (not readyToSet) {                                                                                          \
0999         base_type::elements_ = std::get<1>(NAME);                                                                    \
1000         readyToSet = true;                                                                                           \
1001       }                                                                                                              \
1002       base_type::BOOST_PP_CAT(NAME, Parameters_) = [&]() -> auto {                                                   \
1003         if (base_type::elements_ != std::get<1>(NAME))                                                               \
1004           throw std::runtime_error(                                                                                  \
1005             "In constructor by column pointers: number of elements not equal for every column: "                     \
1006             BOOST_PP_STRINGIZE(NAME));                                                                               \
1007         if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                        \
1008           if (Metadata:: BOOST_PP_CAT(ParametersTypeOf_, NAME)::                                                     \
1009             checkAlignment(std::get<0>(NAME).tupleOrPointer(), alignment))                                           \
1010               throw std::runtime_error("In constructor by column: misaligned column: " #NAME);                       \
1011         return std::get<0>(NAME);                                                                                    \
1012           }();                                                                                                       \
1013       ,                                                                                                              \
1014     /* Column */                                                                                                     \
1015       if (not readyToSet) {                                                                                          \
1016         base_type::elements_ = std::get<1>(NAME);                                                                    \
1017         readyToSet = true;                                                                                           \
1018       }                                                                                                              \
1019       base_type::BOOST_PP_CAT(NAME, Parameters_) = [&]() -> auto {                                                   \
1020         if (base_type::elements_ != std::get<1>(NAME))                                                               \
1021           throw std::runtime_error(                                                                                  \
1022             "In constructor by column pointers: number of elements not equal for every column: "                     \
1023             BOOST_PP_STRINGIZE(NAME));                                                                               \
1024         if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                        \
1025           if (Metadata:: BOOST_PP_CAT(ParametersTypeOf_, NAME)::                                                     \
1026             checkAlignment(std::get<0>(NAME).tupleOrPointer(), alignment))                                           \
1027               throw std::runtime_error("In constructor by column: misaligned column: " #NAME);                       \
1028         return std::get<0>(NAME);                                                                                    \
1029           }();                                                                                                       \
1030       ,                                                                                                              \
1031     /* Eigen column */                                                                                               \
1032       if (not readyToSet) {                                                                                          \
1033         base_type::elements_ = std::get<1>(NAME);                                                                    \
1034         readyToSet = true;                                                                                           \
1035       }                                                                                                              \
1036       base_type::BOOST_PP_CAT(NAME, Parameters_) = [&]() -> auto {                                                   \
1037         if (cms::soa::alignSize(base_type::elements_ * sizeof(CPP_TYPE::Scalar), alignment)                          \
1038                   / sizeof(CPP_TYPE::Scalar) != std::get<0>(NAME).stride_) {                                         \
1039           throw std::runtime_error(                                                                                  \
1040             "In constructor by column pointers: stride not equal between eigen columns: "                            \
1041             BOOST_PP_STRINGIZE(NAME));                                                                               \
1042         }                                                                                                            \
1043         if (base_type::elements_ != std::get<1>(NAME))                                                               \
1044         throw std::runtime_error(                                                                                    \
1045           "In constructor by column pointers: number of elements not equal for every column: "                       \
1046           BOOST_PP_STRINGIZE(NAME));                                                                                 \
1047         if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                        \
1048           if (Metadata:: BOOST_PP_CAT(ParametersTypeOf_, NAME)::                                                     \
1049             checkAlignment(std::get<0>(NAME).tupleOrPointer(), alignment))                                           \
1050               throw std::runtime_error("In constructor by column: misaligned column: " #NAME);                       \
1051         return std::get<0>(NAME);                                                                                    \
1052         }();                                                                                                         \
1053   )
1054 // clang-format on
1055 
1056 #define _INITIALIZE_VIEW_PARAMETERS_AND_SIZE(R, DATA, TYPE_NAME)                            \
1057   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
1058               BOOST_PP_EMPTY(),                                                             \
1059               BOOST_PP_EXPAND(_INITIALIZE_VIEW_PARAMETERS_AND_SIZE_IMPL TYPE_NAME))
1060 
1061 /**
1062  * Generator of parameters for (non-const) element subclass (expanded comma separated).
1063  */
1064 #define _DECLARE_VIEW_ELEMENT_VALUE_ARG_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
1065   (typename BOOST_PP_CAT(Metadata::ParametersTypeOf_, NAME) NAME)
1066 
1067 #define _DECLARE_VIEW_ELEMENT_VALUE_ARG(R, DATA, TYPE_NAME)                                 \
1068   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
1069               BOOST_PP_EMPTY(),                                                             \
1070               BOOST_PP_EXPAND(_DECLARE_VIEW_ELEMENT_VALUE_ARG_IMPL TYPE_NAME))
1071 
1072 /**
1073  * Generator of element members initializer.
1074  */
1075 #define _DECLARE_VIEW_ELEM_MEMBER_INIT_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS, DATA) (NAME(DATA, NAME))
1076 
1077 #define _DECLARE_VIEW_ELEM_MEMBER_INIT(R, DATA, TYPE_NAME)                                  \
1078   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
1079               BOOST_PP_EMPTY(),                                                             \
1080               BOOST_PP_EXPAND(_DECLARE_VIEW_ELEM_MEMBER_INIT_IMPL BOOST_PP_TUPLE_PUSH_BACK(TYPE_NAME, DATA)))
1081 
1082 /**
1083  * Generator of the member-by-member copy operator of the element subclass.
1084  */
1085 #define _DECLARE_VIEW_ELEMENT_VALUE_COPY_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                   \
1086   if constexpr (Metadata::BOOST_PP_CAT(ColumnTypeOf_, NAME) != cms::soa::SoAColumnType::scalar) { \
1087     NAME() = _soa_impl_other.NAME();                                                              \
1088   }
1089 
1090 #define _DECLARE_VIEW_ELEMENT_VALUE_COPY(R, DATA, TYPE_NAME)                                \
1091   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
1092               BOOST_PP_EMPTY(),                                                             \
1093               BOOST_PP_EXPAND(_DECLARE_VIEW_ELEMENT_VALUE_COPY_IMPL TYPE_NAME))
1094 
1095 /**
1096  * Assign the value of the view from the values in the value_element.
1097  */
1098 // clang-format off
1099 #define _TRIVIAL_VIEW_ASSIGN_VALUE_ELEMENT_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                    \
1100   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                        \
1101       /* Scalar (empty) */                                                                                           \
1102       ,                                                                                                              \
1103       /* Column */                                                                                                   \
1104       NAME() = _soa_impl_value.NAME;                                                                                 \
1105       ,                                                                                                              \
1106       /* Eigen column */                                                                                             \
1107       NAME() = _soa_impl_value.NAME;                                                                                 \
1108 )
1109 // clang-format on
1110 
1111 #define _TRIVIAL_VIEW_ASSIGN_VALUE_ELEMENT(R, DATA, TYPE_NAME)                              \
1112   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
1113               BOOST_PP_EMPTY(),                                                             \
1114               BOOST_PP_EXPAND(_TRIVIAL_VIEW_ASSIGN_VALUE_ELEMENT_IMPL TYPE_NAME))
1115 
1116 /**
1117  * Declaration of the private members of the const element subclass
1118  */
1119 // clang-format off
1120 #define _DECLARE_VIEW_ELEMENT_VALUE_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                    \
1121   typename cms::soa::SoAValue_ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template                      \
1122               DataType<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::template                                     \
1123                   Alignment<conditionalAlignment>::template Value<restrictQualify>                                   \
1124       NAME;
1125 // clang-format on
1126 
1127 #define _DECLARE_VIEW_ELEMENT_VALUE_MEMBER(R, DATA, TYPE_NAME)                              \
1128   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
1129               BOOST_PP_EMPTY(),                                                             \
1130               BOOST_PP_EXPAND(_DECLARE_VIEW_ELEMENT_VALUE_MEMBER_IMPL TYPE_NAME))
1131 
1132 /**
1133  * Parameters passed to element subclass constructor in operator[]
1134  *
1135  * The use of const_cast (inside cms::soa::non_const_ptr) is safe because the constructor of a View binds only to
1136  * non-const arguments.
1137  */
1138 #define _DECLARE_VIEW_ELEMENT_CONSTR_CALL_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS) \
1139   (cms::soa::const_cast_SoAParametersImpl(base_type::BOOST_PP_CAT(NAME, Parameters_)))
1140 
1141 #define _DECLARE_VIEW_ELEMENT_CONSTR_CALL(R, DATA, TYPE_NAME)                               \
1142   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
1143               BOOST_PP_EMPTY(),                                                             \
1144               BOOST_PP_EXPAND(_DECLARE_VIEW_ELEMENT_CONSTR_CALL_IMPL TYPE_NAME))
1145 /**
1146  * Direct access to column pointer and indexed access
1147  */
1148 // clang-format off
1149 #define _DECLARE_VIEW_SOA_ACCESSOR_IMPL(VALUE_TYPE, CPP_TYPE, NAME, ARGS)                                            \
1150   /* Column or scalar */                                                                                             \
1151   SOA_HOST_DEVICE SOA_INLINE                                                                                         \
1152   typename cms::soa::SoAAccessors<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::                                  \
1153         template ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template AccessType<                       \
1154             cms::soa::SoAAccessType::mutableAccess>::template Alignment<conditionalAlignment>::                      \
1155                  template RestrictQualifier<restrictQualify>::NoParamReturnType                                      \
1156   NAME() {                                                                                                           \
1157     return typename cms::soa::SoAAccessors<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::                         \
1158         template ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template AccessType<                       \
1159             cms::soa::SoAAccessType::mutableAccess>::template Alignment<conditionalAlignment>::                      \
1160                 template RestrictQualifier<restrictQualify>(cms::soa::const_cast_SoAParametersImpl(                  \
1161                     base_type:: BOOST_PP_CAT(NAME, Parameters_)))();                                                 \
1162   }                                                                                                                  \
1163   SOA_HOST_DEVICE SOA_INLINE                                                                                         \
1164   typename cms::soa::SoAAccessors<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::                                  \
1165         template ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template AccessType<                       \
1166             cms::soa::SoAAccessType::mutableAccess>::template Alignment<conditionalAlignment>::                      \
1167                  template RestrictQualifier<restrictQualify>::ParamReturnType                                        \
1168   NAME(size_type _soa_impl_index) {                                                                                  \
1169     if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {                                               \
1170       if (_soa_impl_index >= base_type::elements_ or _soa_impl_index < 0)                                            \
1171         SOA_THROW_OUT_OF_RANGE("Out of range index in mutable " #NAME "(size_type index)",                           \
1172           _soa_impl_index, base_type::elements_)                                                                     \
1173     }                                                                                                                \
1174     return typename cms::soa::SoAAccessors<typename BOOST_PP_CAT(Metadata::TypeOf_, NAME)>::                         \
1175         template ColumnType<BOOST_PP_CAT(Metadata::ColumnTypeOf_, NAME)>::template AccessType<                       \
1176             cms::soa::SoAAccessType::mutableAccess>::template Alignment<conditionalAlignment>::                      \
1177                 template RestrictQualifier<restrictQualify>(cms::soa::const_cast_SoAParametersImpl(                  \
1178                     base_type:: BOOST_PP_CAT(NAME, Parameters_)))(_soa_impl_index);                                  \
1179   }
1180 // clang-format on
1181 
1182 #define _DECLARE_VIEW_SOA_ACCESSOR(R, DATA, TYPE_NAME)                                      \
1183   BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_TUPLE_ELEM(0, TYPE_NAME), _VALUE_LAST_COLUMN_TYPE), \
1184               BOOST_PP_EMPTY(),                                                             \
1185               BOOST_PP_EXPAND(_DECLARE_VIEW_SOA_ACCESSOR_IMPL TYPE_NAME))
1186 
1187 #ifdef DEBUG
1188 #define _DO_RANGECHECK true
1189 #else
1190 #define _DO_RANGECHECK false
1191 #endif
1192 
1193 /*
1194  * A macro defining a SoA layout (collection of scalars and columns of equal lengths)
1195  */
1196 // clang-format off
1197 #define GENERATE_SOA_LAYOUT(CLASS, ...)                                                                                \
1198   template <CMS_SOA_BYTE_SIZE_TYPE ALIGNMENT = cms::soa::CacheLineSize::defaultSize,                                   \
1199             bool ALIGNMENT_ENFORCEMENT = cms::soa::AlignmentEnforcement::relaxed>                                      \
1200   struct CLASS {                                                                                                       \
1201     /* these could be moved to an external type trait to free up the symbol names */                                   \
1202     using self_type = CLASS;                                                                                           \
1203     using AlignmentEnforcement = cms::soa::AlignmentEnforcement;                                                       \
1204                                                                                                                        \
1205     /* For CUDA applications, we align to the 128 bytes of the cache lines.                                            \
1206      * See https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-memory-3-0 this is still valid      \
1207      * up to compute capability 8.X.                                                                                   \
1208      */                                                                                                                \
1209     using size_type = cms::soa::size_type;                                                                             \
1210     using byte_size_type = cms::soa::byte_size_type;                                                                   \
1211     constexpr static byte_size_type defaultAlignment = 128;                                                            \
1212     constexpr static byte_size_type alignment = ALIGNMENT;                                                             \
1213     constexpr static bool alignmentEnforcement = ALIGNMENT_ENFORCEMENT;                                                \
1214     constexpr static byte_size_type conditionalAlignment =                                                             \
1215         alignmentEnforcement == cms::soa::AlignmentEnforcement::enforced ? alignment : 0;                              \
1216     /* Those typedefs avoid having commas in macros (which is problematic) */                                          \
1217     template <cms::soa::SoAColumnType COLUMN_TYPE, class C>                                                            \
1218     using SoAValueWithConf = cms::soa::SoAValue<COLUMN_TYPE, C, conditionalAlignment>;                                 \
1219                                                                                                                        \
1220     template <cms::soa::SoAColumnType COLUMN_TYPE, class C>                                                            \
1221     using SoAConstValueWithConf = cms::soa::SoAConstValue<COLUMN_TYPE, C, conditionalAlignment>;                       \
1222                                                                                                                        \
1223     template <CMS_SOA_BYTE_SIZE_TYPE VIEW_ALIGNMENT = cms::soa::CacheLineSize::defaultSize,                            \
1224             bool VIEW_ALIGNMENT_ENFORCEMENT = cms::soa::AlignmentEnforcement::relaxed,                                 \
1225             bool RESTRICT_QUALIFY = cms::soa::RestrictQualify::Default,                                                \
1226             bool RANGE_CHECKING = cms::soa::RangeChecking::Default>                                                    \
1227     struct ViewTemplateFreeParams;                                                                                     \
1228                                                                                                                        \
1229     /* dump the SoA internal structure */                                                                              \
1230     SOA_HOST_ONLY                                                                                                      \
1231     void soaToStreamInternal(std::ostream & _soa_impl_os) const {                                                      \
1232       _soa_impl_os << #CLASS "(" << elements_ << " elements, byte alignement= " << alignment << ", @"<< mem_ <<"): "   \
1233          << std::endl;                                                                                                 \
1234       _soa_impl_os << "  sizeof(" #CLASS "): " << sizeof(CLASS) << std::endl;                                          \
1235       byte_size_type _soa_impl_offset = 0;                                                                             \
1236       _ITERATE_ON_ALL(_DECLARE_SOA_STREAM_INFO, ~, __VA_ARGS__)                                                        \
1237       _soa_impl_os << "Final offset = " << _soa_impl_offset << " computeDataSize(...): " << computeDataSize(elements_) \
1238               << std::endl;                                                                                            \
1239       _soa_impl_os << std::endl;                                                                                       \
1240     }                                                                                                                  \
1241                                                                                                                        \
1242     /* Helper function used by caller to externally allocate the storage */                                            \
1243     static constexpr byte_size_type computeDataSize(size_type elements) {                                              \
1244       byte_size_type _soa_impl_ret = 0;                                                                                \
1245       _ITERATE_ON_ALL(_ACCUMULATE_SOA_ELEMENT, ~, __VA_ARGS__)                                                         \
1246       return _soa_impl_ret;                                                                                            \
1247     }                                                                                                                  \
1248                                                                                                                        \
1249     /**                                                                                                                \
1250      * Helper/friend class allowing SoA introspection.                                                                 \
1251      */                                                                                                                \
1252     struct Metadata {                                                                                                  \
1253       friend CLASS;                                                                                                    \
1254       SOA_HOST_DEVICE SOA_INLINE size_type size() const { return parent_.elements_; }                                  \
1255       SOA_HOST_DEVICE SOA_INLINE byte_size_type byteSize() const { return parent_.byteSize_; }                         \
1256       SOA_HOST_DEVICE SOA_INLINE byte_size_type alignment() const { return CLASS::alignment; }                         \
1257       SOA_HOST_DEVICE SOA_INLINE std::byte* data() { return parent_.mem_; }                                            \
1258       SOA_HOST_DEVICE SOA_INLINE const std::byte* data() const { return parent_.mem_; }                                \
1259       SOA_HOST_DEVICE SOA_INLINE std::byte* nextByte() const { return parent_.mem_ + parent_.byteSize_; }              \
1260       SOA_HOST_DEVICE SOA_INLINE CLASS cloneToNewAddress(std::byte* _soa_impl_addr) const {                            \
1261         return CLASS(_soa_impl_addr, parent_.elements_);                                                               \
1262       }                                                                                                                \
1263                                                                                                                        \
1264       _ITERATE_ON_ALL(_DEFINE_METADATA_MEMBERS, ~, __VA_ARGS__)                                                        \
1265                                                                                                                        \
1266       struct value_element {                                                                                           \
1267         SOA_HOST_DEVICE SOA_INLINE value_element                                                                       \
1268           BOOST_PP_IF(                                                                                                 \
1269             BOOST_PP_SEQ_SIZE(_ITERATE_ON_ALL(_VALUE_ELEMENT_CTOR_ARGS, ~, __VA_ARGS__) ),                             \
1270             (_ITERATE_ON_ALL_COMMA(_VALUE_ELEMENT_CTOR_ARGS, ~, __VA_ARGS__)):,                                        \
1271             ())                                                                                                        \
1272           BOOST_PP_TUPLE_ENUM(BOOST_PP_IF(                                                                             \
1273             BOOST_PP_SEQ_SIZE(_ITERATE_ON_ALL(_VALUE_ELEMENT_CTOR_ARGS, ~, __VA_ARGS__)),                              \
1274             BOOST_PP_SEQ_TO_TUPLE(_ITERATE_ON_ALL(_VALUE_ELEMENT_INITIALIZERS, ~, __VA_ARGS__)),                       \
1275             ()                                                                                                         \
1276           )                                                                                                            \
1277         )                                                                                                              \
1278         {}                                                                                                             \
1279                                                                                                                        \
1280         _ITERATE_ON_ALL(_DEFINE_VALUE_ELEMENT_MEMBERS, ~, __VA_ARGS__)                                                 \
1281       };                                                                                                               \
1282                                                                                                                        \
1283       Metadata& operator=(const Metadata&) = delete;                                                                   \
1284       Metadata(const Metadata&) = delete;                                                                              \
1285                                                                                                                        \
1286     private:                                                                                                           \
1287       SOA_HOST_DEVICE SOA_INLINE Metadata(const CLASS& _soa_impl_parent) : parent_(_soa_impl_parent) {}                \
1288       const CLASS& parent_;                                                                                            \
1289       using ParentClass = CLASS;                                                                                       \
1290     };                                                                                                                 \
1291                                                                                                                        \
1292     friend Metadata;                                                                                                   \
1293                                                                                                                        \
1294     SOA_HOST_DEVICE SOA_INLINE const Metadata metadata() const { return Metadata(*this); }                             \
1295     SOA_HOST_DEVICE SOA_INLINE Metadata metadata() { return Metadata(*this); }                                         \
1296                                                                                                                        \
1297     template <CMS_SOA_BYTE_SIZE_TYPE VIEW_ALIGNMENT,                                                                   \
1298               bool VIEW_ALIGNMENT_ENFORCEMENT,                                                                         \
1299               bool RESTRICT_QUALIFY,                                                                                   \
1300               bool RANGE_CHECKING>                                                                                     \
1301     struct ConstViewTemplateFreeParams {                                                                               \
1302       /* these could be moved to an external type trait to free up the symbol names */                                 \
1303       using self_type = ConstViewTemplateFreeParams;                                                                   \
1304       using BOOST_PP_CAT(CLASS, _parametrized) = CLASS<VIEW_ALIGNMENT, VIEW_ALIGNMENT_ENFORCEMENT>;                    \
1305       using size_type = cms::soa::size_type;                                                                           \
1306       using byte_size_type = cms::soa::byte_size_type;                                                                 \
1307       using AlignmentEnforcement = cms::soa::AlignmentEnforcement;                                                     \
1308                                                                                                                        \
1309       template <CMS_SOA_BYTE_SIZE_TYPE, bool, bool, bool>                                                              \
1310       friend struct ViewTemplateFreeParams;                                                                            \
1311                                                                                                                        \
1312       template <CMS_SOA_BYTE_SIZE_TYPE, bool, bool, bool>                                                              \
1313       friend struct ConstViewTemplateFreeParams;                                                                       \
1314                                                                                                                        \
1315       /* For CUDA applications, we align to the 128 bytes of the cache lines.                                          \
1316         * See https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-memory-3-0 this is still valid   \
1317         * up to compute capability 8.X.                                                                                \
1318         */                                                                                                             \
1319       constexpr static byte_size_type defaultAlignment = cms::soa::CacheLineSize::defaultSize;                         \
1320       constexpr static byte_size_type alignment = VIEW_ALIGNMENT;                                                      \
1321       constexpr static bool alignmentEnforcement = VIEW_ALIGNMENT_ENFORCEMENT;                                         \
1322       constexpr static byte_size_type conditionalAlignment =                                                           \
1323           alignmentEnforcement == AlignmentEnforcement::enforced ? alignment : 0;                                      \
1324       constexpr static bool restrictQualify = RESTRICT_QUALIFY;                                                        \
1325       constexpr static bool rangeChecking = RANGE_CHECKING;                                                            \
1326                                                                                                                        \
1327       /**                                                                                                              \
1328        * Helper/friend class allowing SoA introspection.                                                               \
1329        */                                                                                                              \
1330       struct Metadata {                                                                                                \
1331         friend ConstViewTemplateFreeParams;                                                                            \
1332         SOA_HOST_DEVICE SOA_INLINE size_type size() const { return parent_.elements_; }                                \
1333         /* Alias layout to name-derived identifyer to allow simpler definitions */                                     \
1334         using TypeOf_Layout = BOOST_PP_CAT(CLASS, _parametrized);                                                      \
1335                                                                                                                        \
1336         /* Alias member types to name-derived identifyer to allow simpler definitions */                               \
1337         _ITERATE_ON_ALL(_DECLARE_VIEW_MEMBER_TYPE_ALIAS, BOOST_PP_EMPTY(), __VA_ARGS__)                                \
1338         _ITERATE_ON_ALL(_DECLARE_VIEW_MEMBER_CONST_POINTERS, ~, __VA_ARGS__)                                           \
1339                                                                                                                        \
1340         /* Forbid copying to avoid const correctness evasion */                                                        \
1341         Metadata& operator=(const Metadata&) = delete;                                                                 \
1342         Metadata(const Metadata&) = delete;                                                                            \
1343                                                                                                                        \
1344       private:                                                                                                         \
1345         SOA_HOST_DEVICE SOA_INLINE Metadata(const ConstViewTemplateFreeParams& _soa_impl_parent)                       \
1346         : parent_(_soa_impl_parent) {}                                                                                 \
1347         const ConstViewTemplateFreeParams& parent_;                                                                    \
1348       };                                                                                                               \
1349                                                                                                                        \
1350       friend Metadata;                                                                                                 \
1351                                                                                                                        \
1352       /**                                                                                                              \
1353       * Helper/friend class allowing access to size from columns.                                                      \
1354       */                                                                                                               \
1355       struct Metarecords {                                                                                             \
1356         friend ConstViewTemplateFreeParams;                                                                            \
1357         Metarecords(const ConstViewTemplateFreeParams& _soa_impl_parent) :                                             \
1358                     parent_(_soa_impl_parent), _ITERATE_ON_ALL_COMMA(_STRUCT_ELEMENT_INITIALIZERS, ~, __VA_ARGS__) {}  \
1359         _ITERATE_ON_ALL(_CONST_ACCESSORS_STRUCT_MEMBERS, ~, __VA_ARGS__)                                               \
1360         private:                                                                                                       \
1361           const ConstViewTemplateFreeParams& parent_;                                                                  \
1362           _ITERATE_ON_ALL(_DECLARE_STRUCT_CONST_DATA_MEMBER, ~, __VA_ARGS__)                                           \
1363       };                                                                                                               \
1364       SOA_HOST_DEVICE SOA_INLINE const Metadata metadata() const { return Metadata(*this); }                           \
1365       SOA_HOST_DEVICE SOA_INLINE const Metarecords records() const { return Metarecords(*this); }                      \
1366                                                                                                                        \
1367       /* Trivial constuctor */                                                                                         \
1368       ConstViewTemplateFreeParams() = default;                                                                         \
1369                                                                                                                        \
1370       /* Constructor relying the layout */                                                                             \
1371       SOA_HOST_ONLY ConstViewTemplateFreeParams(const Metadata::TypeOf_Layout& layout)                                 \
1372       : elements_(layout.metadata().size()),                                                                           \
1373         _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_MEMBER_INITIALIZERS, ~, __VA_ARGS__) {}                                    \
1374                                                                                                                        \
1375       /* Constructor relying on individually provided column structs */                                                \
1376       SOA_HOST_ONLY ConstViewTemplateFreeParams(_ITERATE_ON_ALL_COMMA(                                                 \
1377                 _DECLARE_CONST_VIEW_CONSTRUCTOR_COLUMNS, ~, __VA_ARGS__)) {                                            \
1378         bool readyToSet = false;                                                                                       \
1379         _ITERATE_ON_ALL(_INITIALIZE_CONST_VIEW_PARAMETERS_AND_SIZE, ~, __VA_ARGS__)                                    \
1380       }                                                                                                                \
1381                                                                                                                        \
1382       /* Copiable */                                                                                                   \
1383       ConstViewTemplateFreeParams(ConstViewTemplateFreeParams const&) = default;                                       \
1384       ConstViewTemplateFreeParams& operator=(ConstViewTemplateFreeParams const&) = default;                            \
1385                                                                                                                        \
1386       /* Copy constructor for other parameters */                                                                      \
1387       template <CMS_SOA_BYTE_SIZE_TYPE OTHER_VIEW_ALIGNMENT,                                                           \
1388                 bool OTHER_VIEW_ALIGNMENT_ENFORCEMENT,                                                                 \
1389                 bool OTHER_RESTRICT_QUALIFY,                                                                           \
1390                 bool OTHER_RANGE_CHECKING>                                                                             \
1391       ConstViewTemplateFreeParams(ConstViewTemplateFreeParams<OTHER_VIEW_ALIGNMENT,                                    \
1392         OTHER_VIEW_ALIGNMENT_ENFORCEMENT, OTHER_RESTRICT_QUALIFY, OTHER_RANGE_CHECKING> const& other)                  \
1393         : ConstViewTemplateFreeParams{other.elements_,                                                                 \
1394             _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_OTHER_MEMBER_LIST, BOOST_PP_EMPTY(), __VA_ARGS__)                      \
1395           } {}                                                                                                         \
1396       /* Copy operator for other parameters */                                                                         \
1397       template <CMS_SOA_BYTE_SIZE_TYPE OTHER_VIEW_ALIGNMENT,                                                           \
1398           bool OTHER_VIEW_ALIGNMENT_ENFORCEMENT,                                                                       \
1399           bool OTHER_RESTRICT_QUALIFY,                                                                                 \
1400           bool OTHER_RANGE_CHECKING>                                                                                   \
1401       ConstViewTemplateFreeParams& operator=(ConstViewTemplateFreeParams<OTHER_VIEW_ALIGNMENT,                         \
1402           OTHER_VIEW_ALIGNMENT_ENFORCEMENT, OTHER_RESTRICT_QUALIFY, OTHER_RANGE_CHECKING> const& other)                \
1403           { *this = other; }                                                                                           \
1404                                                                                                                        \
1405       /* Movable */                                                                                                    \
1406       ConstViewTemplateFreeParams(ConstViewTemplateFreeParams &&) = default;                                           \
1407       ConstViewTemplateFreeParams& operator=(ConstViewTemplateFreeParams &&) = default;                                \
1408                                                                                                                        \
1409       /* Trivial destuctor */                                                                                          \
1410       ~ConstViewTemplateFreeParams() = default;                                                                        \
1411                                                                                                                        \
1412       /* AoS-like accessor (const) */                                                                                  \
1413       struct const_element {                                                                                           \
1414         SOA_HOST_DEVICE SOA_INLINE                                                                                     \
1415         const_element(size_type _soa_impl_index, /* Declare parameters */                                              \
1416                       _ITERATE_ON_ALL_COMMA(_DECLARE_CONST_VIEW_ELEMENT_VALUE_ARG, ~, __VA_ARGS__))                \
1417                       : _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_CONST_ELEM_MEMBER_INIT, _soa_impl_index, __VA_ARGS__) {}   \
1418         _ITERATE_ON_ALL(_DECLARE_VIEW_CONST_ELEMENT_ACCESSOR, ~, __VA_ARGS__)                                          \
1419                                                                                                                        \
1420         ENUM_IF_VALID(_ITERATE_ON_ALL(GENERATE_CONST_METHODS, ~, __VA_ARGS__))                                         \
1421                                                                                                                        \
1422         private:                                                                                                       \
1423         _ITERATE_ON_ALL(_DECLARE_VIEW_CONST_ELEMENT_VALUE_MEMBER, ~, __VA_ARGS__)                                      \
1424       };                                                                                                               \
1425                                                                                                                        \
1426         SOA_HOST_DEVICE SOA_INLINE                                                                                     \
1427         const_element operator[](size_type _soa_impl_index) const {                                                    \
1428           if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {                                           \
1429             if (_soa_impl_index >= elements_ or _soa_impl_index < 0)                                                   \
1430               SOA_THROW_OUT_OF_RANGE("Out of range index in ConstViewTemplateFreeParams ::operator[]",                 \
1431                 _soa_impl_index, elements_)                                                                            \
1432           }                                                                                                            \
1433           return const_element{                                                                                        \
1434             _soa_impl_index, _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_CONST_ELEMENT_CONSTR_CALL, ~, __VA_ARGS__)            \
1435           };                                                                                                           \
1436         }                                                                                                              \
1437                                                                                                                        \
1438         /* const accessors */                                                                                          \
1439         _ITERATE_ON_ALL(_DECLARE_VIEW_SOA_CONST_ACCESSOR, ~, __VA_ARGS__)                                              \
1440                                                                                                                        \
1441         /* dump the SoA internal structure */                                                                          \
1442         template <typename T>                                                                                          \
1443         SOA_HOST_ONLY friend void dump();                                                                              \
1444                                                                                                                        \
1445         private:                                                                                                       \
1446           size_type elements_ = 0;                                                                                     \
1447           _ITERATE_ON_ALL(_DECLARE_CONST_VIEW_SOA_MEMBER, ~, __VA_ARGS__)                                              \
1448       };                                                                                                               \
1449                                                                                                                        \
1450     template <bool RESTRICT_QUALIFY, bool RANGE_CHECKING>                                                              \
1451     using ConstViewTemplate = ConstViewTemplateFreeParams<ALIGNMENT, ALIGNMENT_ENFORCEMENT, RESTRICT_QUALIFY,          \
1452       RANGE_CHECKING>;                                                                                                 \
1453                                                                                                                        \
1454     using ConstView = ConstViewTemplate<cms::soa::RestrictQualify::Default, cms::soa::RangeChecking::Default>;         \
1455                                                                                                                        \
1456     template <CMS_SOA_BYTE_SIZE_TYPE VIEW_ALIGNMENT,                                                                   \
1457               bool VIEW_ALIGNMENT_ENFORCEMENT,                                                                         \
1458               bool RESTRICT_QUALIFY,                                                                                   \
1459               bool RANGE_CHECKING>                                                                                     \
1460       struct ViewTemplateFreeParams                                                                                    \
1461       : public ConstViewTemplateFreeParams<VIEW_ALIGNMENT, VIEW_ALIGNMENT_ENFORCEMENT,                                 \
1462                                            RESTRICT_QUALIFY, RANGE_CHECKING> {                                         \
1463       /* these could be moved to an external type trait to free up the symbol names */                                 \
1464       using self_type = ViewTemplateFreeParams;                                                                        \
1465       using base_type = ConstViewTemplateFreeParams<VIEW_ALIGNMENT, VIEW_ALIGNMENT_ENFORCEMENT,                        \
1466                                                     RESTRICT_QUALIFY, RANGE_CHECKING>;                                 \
1467       using BOOST_PP_CAT(CLASS, _parametrized) = CLASS<VIEW_ALIGNMENT, VIEW_ALIGNMENT_ENFORCEMENT>;                    \
1468       using size_type = cms::soa::size_type;                                                                           \
1469       using byte_size_type = cms::soa::byte_size_type;                                                                 \
1470       using AlignmentEnforcement = cms::soa::AlignmentEnforcement;                                                     \
1471                                                                                                                        \
1472       /* For CUDA applications, we align to the 128 bytes of the cache lines.                                          \
1473        * See https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-memory-3-0 this is still valid    \
1474        * up to compute capability 8.X.                                                                                 \
1475        */                                                                                                              \
1476       constexpr static byte_size_type defaultAlignment = cms::soa::CacheLineSize::defaultSize;                         \
1477       constexpr static byte_size_type alignment = VIEW_ALIGNMENT;                                                      \
1478       constexpr static bool alignmentEnforcement = VIEW_ALIGNMENT_ENFORCEMENT;                                         \
1479       constexpr static byte_size_type conditionalAlignment =                                                           \
1480           alignmentEnforcement == AlignmentEnforcement::enforced ? alignment : 0;                                      \
1481       constexpr static bool restrictQualify = RESTRICT_QUALIFY;                                                        \
1482       constexpr static bool rangeChecking = RANGE_CHECKING;                                                            \
1483                                                                                                                        \
1484       template <CMS_SOA_BYTE_SIZE_TYPE, bool, bool, bool>                                                              \
1485       friend struct ViewTemplateFreeParams;                                                                            \
1486                                                                                                                        \
1487       /**                                                                                                              \
1488        * Helper/friend class allowing SoA introspection.                                                               \
1489        */                                                                                                              \
1490       struct Metadata {                                                                                                \
1491         friend ViewTemplateFreeParams;                                                                                 \
1492         SOA_HOST_DEVICE SOA_INLINE size_type size() const { return parent_.elements_; }                                \
1493         /* Alias layout to name-derived identifyer to allow simpler definitions */                                     \
1494         using TypeOf_Layout = BOOST_PP_CAT(CLASS, _parametrized);                                                      \
1495                                                                                                                        \
1496         /* Alias member types to name-derived identifyer to allow simpler definitions */                               \
1497         _ITERATE_ON_ALL(_DECLARE_VIEW_MEMBER_TYPE_ALIAS, cms::soa::const_cast_SoAParametersImpl, __VA_ARGS__)          \
1498         _ITERATE_ON_ALL(_DECLARE_VIEW_MEMBER_POINTERS, ~, __VA_ARGS__)                                                 \
1499         _ITERATE_ON_ALL(_DECLARE_VIEW_MEMBER_CONST_POINTERS, ~, __VA_ARGS__)                                           \
1500                                                                                                                        \
1501         /* Forbid copying to avoid const correctness evasion */                                                        \
1502         Metadata& operator=(const Metadata&) = delete;                                                                 \
1503         Metadata(const Metadata&) = delete;                                                                            \
1504                                                                                                                        \
1505       private:                                                                                                         \
1506         SOA_HOST_DEVICE SOA_INLINE Metadata(const ViewTemplateFreeParams& _soa_impl_parent)                            \
1507         : parent_(_soa_impl_parent) {}                                                                                 \
1508         const ViewTemplateFreeParams& parent_;                                                                         \
1509       };                                                                                                               \
1510                                                                                                                        \
1511       friend Metadata;                                                                                                 \
1512                                                                                                                        \
1513       /**                                                                                                              \
1514        * Helper/friend class allowing access to size from columns.                                                     \
1515        */                                                                                                              \
1516       struct Metarecords {                                                                                             \
1517         friend ViewTemplateFreeParams;                                                                                 \
1518         Metarecords(const ViewTemplateFreeParams& _soa_impl_parent) :                                                  \
1519                     parent_(_soa_impl_parent), _ITERATE_ON_ALL_COMMA(_STRUCT_ELEMENT_INITIALIZERS, ~, __VA_ARGS__) {}  \
1520         _ITERATE_ON_ALL(_ACCESSORS_STRUCT_MEMBERS, ~, __VA_ARGS__)                                                     \
1521         private:                                                                                                       \
1522           const ViewTemplateFreeParams& parent_;                                                                       \
1523           _ITERATE_ON_ALL(_DECLARE_STRUCT_DATA_MEMBER, ~, __VA_ARGS__)                                                 \
1524       };                                                                                                               \
1525                                                                                                                        \
1526       SOA_HOST_DEVICE SOA_INLINE const Metadata metadata() const { return Metadata(*this); }                           \
1527       SOA_HOST_DEVICE SOA_INLINE Metadata metadata() { return Metadata(*this); }                                       \
1528       SOA_HOST_DEVICE SOA_INLINE const Metarecords records() const { return Metarecords(*this); }                      \
1529       SOA_HOST_DEVICE SOA_INLINE Metarecords records() { return Metarecords(*this); }                                  \
1530                                                                                                                        \
1531       /* Trivial constuctor */                                                                                         \
1532       ViewTemplateFreeParams() = default;                                                                              \
1533                                                                                                                        \
1534       /* Constructor relying on user provided layouts or views */                                                      \
1535       SOA_HOST_ONLY ViewTemplateFreeParams(const Metadata::TypeOf_Layout& layout)                                      \
1536         : base_type{layout} {}                                                                                         \
1537                                                                                                                        \
1538       /* Constructor relying on individually provided column structs */                                                \
1539       SOA_HOST_ONLY ViewTemplateFreeParams(                                                                            \
1540                     _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_CONSTRUCTOR_COLUMNS, ~, __VA_ARGS__)) {                        \
1541         bool readyToSet = false;                                                                                       \
1542         _ITERATE_ON_ALL(_INITIALIZE_VIEW_PARAMETERS_AND_SIZE, ~, __VA_ARGS__)                                          \
1543       }                                                                                                                \
1544                                                                                                                        \
1545       /* Copiable */                                                                                                   \
1546       ViewTemplateFreeParams(ViewTemplateFreeParams const&) = default;                                                 \
1547       ViewTemplateFreeParams& operator=(ViewTemplateFreeParams const&) = default;                                      \
1548                                                                                                                        \
1549       /* Copy constructor for other parameters */                                                                      \
1550       template <CMS_SOA_BYTE_SIZE_TYPE OTHER_VIEW_ALIGNMENT,                                                           \
1551                 bool OTHER_VIEW_ALIGNMENT_ENFORCEMENT,                                                                 \
1552                 bool OTHER_RESTRICT_QUALIFY,                                                                           \
1553                 bool OTHER_RANGE_CHECKING>                                                                             \
1554       ViewTemplateFreeParams(ViewTemplateFreeParams<OTHER_VIEW_ALIGNMENT, OTHER_VIEW_ALIGNMENT_ENFORCEMENT,            \
1555                                                     OTHER_RESTRICT_QUALIFY, OTHER_RANGE_CHECKING> const& other)        \
1556       : base_type{other.elements_,                                                                                     \
1557                   _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_OTHER_MEMBER_LIST, BOOST_PP_EMPTY(), __VA_ARGS__)                \
1558                 } {}                                                                                                   \
1559       /* Copy operator for other parameters */                                                                         \
1560       template <CMS_SOA_BYTE_SIZE_TYPE OTHER_VIEW_ALIGNMENT,                                                           \
1561                 bool OTHER_VIEW_ALIGNMENT_ENFORCEMENT,                                                                 \
1562                 bool OTHER_RESTRICT_QUALIFY,                                                                           \
1563                 bool OTHER_RANGE_CHECKING>                                                                             \
1564       ViewTemplateFreeParams& operator=(ViewTemplateFreeParams<OTHER_VIEW_ALIGNMENT,                                   \
1565         OTHER_VIEW_ALIGNMENT_ENFORCEMENT, OTHER_RESTRICT_QUALIFY, OTHER_RANGE_CHECKING> const& other)                  \
1566           { static_cast<base_type>(*this) = static_cast<base_type>(other); }                                           \
1567                                                                                                                        \
1568       /* Movable */                                                                                                    \
1569       ViewTemplateFreeParams(ViewTemplateFreeParams &&) = default;                                                     \
1570       ViewTemplateFreeParams& operator=(ViewTemplateFreeParams &&) = default;                                          \
1571                                                                                                                        \
1572       /* Trivial destuctor */                                                                                          \
1573       ~ViewTemplateFreeParams() = default;                                                                             \
1574                                                                                                                        \
1575       /* AoS-like accessor (const) */                                                                                  \
1576       using const_element = typename base_type::const_element;                                                         \
1577                                                                                                                        \
1578       using base_type::operator[];                                                                                     \
1579                                                                                                                        \
1580       /* AoS-like accessor (mutable) */                                                                                \
1581       struct element {                                                                                                 \
1582         SOA_HOST_DEVICE SOA_INLINE                                                                                     \
1583         element(size_type _soa_impl_index, /* Declare parameters */                                                    \
1584                 _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_ELEMENT_VALUE_ARG, ~, __VA_ARGS__))                                \
1585             : _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_ELEM_MEMBER_INIT, _soa_impl_index, __VA_ARGS__) {}                   \
1586         SOA_HOST_DEVICE SOA_INLINE                                                                                     \
1587         element& operator=(const element& _soa_impl_other) {                                                           \
1588           _ITERATE_ON_ALL(_DECLARE_VIEW_ELEMENT_VALUE_COPY, ~, __VA_ARGS__)                                            \
1589           return *this;                                                                                                \
1590         }                                                                                                              \
1591         SOA_HOST_DEVICE SOA_INLINE                                                                                     \
1592         element& operator=(const const_element& _soa_impl_other) {                                                     \
1593           _ITERATE_ON_ALL(_DECLARE_VIEW_ELEMENT_VALUE_COPY, ~, __VA_ARGS__)                                            \
1594           return *this;                                                                                                \
1595         }                                                                                                              \
1596         /* Extra operator=() for mutable element to emulate the aggregate initialisation syntax */                     \
1597         SOA_HOST_DEVICE SOA_INLINE constexpr element & operator=(const typename                                        \
1598             BOOST_PP_CAT(CLASS, _parametrized)::Metadata::value_element _soa_impl_value) {                             \
1599           _ITERATE_ON_ALL(_TRIVIAL_VIEW_ASSIGN_VALUE_ELEMENT, ~, __VA_ARGS__)                                          \
1600           return *this;                                                                                                \
1601         }                                                                                                              \
1602                                                                                                                        \
1603         ENUM_IF_VALID(_ITERATE_ON_ALL(GENERATE_METHODS, ~, __VA_ARGS__))                                               \
1604         ENUM_IF_VALID(_ITERATE_ON_ALL(GENERATE_CONST_METHODS, ~, __VA_ARGS__))                                         \
1605                                                                                                                        \
1606         _ITERATE_ON_ALL(_DECLARE_VIEW_ELEMENT_VALUE_MEMBER, ~, __VA_ARGS__)                                            \
1607       };                                                                                                               \
1608                                                                                                                        \
1609       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
1610       element operator[](size_type _soa_impl_index) {                                                                  \
1611         if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {                                             \
1612           if (_soa_impl_index >= base_type::elements_ or _soa_impl_index < 0)                                          \
1613             SOA_THROW_OUT_OF_RANGE("Out of range index in ViewTemplateFreeParams ::operator[]",                        \
1614               _soa_impl_index, base_type::elements_)                                                                   \
1615         }                                                                                                              \
1616         return element{_soa_impl_index, _ITERATE_ON_ALL_COMMA(_DECLARE_VIEW_ELEMENT_CONSTR_CALL, ~, __VA_ARGS__)};     \
1617       }                                                                                                                \
1618                                                                                                                        \
1619       /* inherit const accessors from ConstView */                                                                     \
1620                                                                                                                        \
1621       /* non-const accessors */                                                                                        \
1622       _ITERATE_ON_ALL(_DECLARE_VIEW_SOA_ACCESSOR, ~, __VA_ARGS__)                                                      \
1623                                                                                                                        \
1624       /* dump the SoA internal structure */                                                                            \
1625       template <typename T>                                                                                            \
1626       SOA_HOST_ONLY friend void dump();                                                                                \
1627     };                                                                                                                 \
1628                                                                                                                        \
1629     template <bool RESTRICT_QUALIFY, bool RANGE_CHECKING>                                                              \
1630     using ViewTemplate = ViewTemplateFreeParams<ALIGNMENT, ALIGNMENT_ENFORCEMENT, RESTRICT_QUALIFY, RANGE_CHECKING>;   \
1631                                                                                                                        \
1632     using View = ViewTemplate<cms::soa::RestrictQualify::Default, cms::soa::RangeChecking::Default>;                   \
1633                                                                                                                        \
1634     /* Helper struct to loop over the columns without using name for non-mutable data */                               \
1635     struct ConstDescriptor {                                                                                           \
1636       ConstDescriptor() = default;                                                                                     \
1637                                                                                                                        \
1638       explicit ConstDescriptor(ConstView const& view)                                                                  \
1639           : buff{ _ITERATE_ON_ALL_COMMA(_ASSIGN_SPAN_TO_COLUMNS, ~, __VA_ARGS__)} {}                                   \
1640                                                                                                                        \
1641       std::tuple<_ITERATE_ON_ALL_COMMA(_DECLARE_CONST_DESCRIPTOR_SPANS, ~, __VA_ARGS__)> buff;                         \
1642       static constexpr size_type num_cols = std::tuple_size<std::tuple<                                                \
1643                                     _ITERATE_ON_ALL_COMMA(_DECLARE_CONST_DESCRIPTOR_SPANS, ~, __VA_ARGS__)>>::value;   \
1644     };                                                                                                                 \
1645                                                                                                                        \
1646     /* Helper struct to loop over the columns without using name for mutable data */                                   \
1647     struct Descriptor {                                                                                                \
1648       Descriptor() = default;                                                                                          \
1649                                                                                                                        \
1650       explicit Descriptor(View& view)                                                                                  \
1651           : buff{ _ITERATE_ON_ALL_COMMA(_ASSIGN_SPAN_TO_COLUMNS, ~, __VA_ARGS__)} {}                                   \
1652                                                                                                                        \
1653       std::tuple<_ITERATE_ON_ALL_COMMA(_DECLARE_DESCRIPTOR_SPANS, ~, __VA_ARGS__)> buff;                               \
1654       static constexpr size_type num_cols = std::tuple_size<std::tuple<                                                \
1655                                     _ITERATE_ON_ALL_COMMA(_DECLARE_DESCRIPTOR_SPANS, ~, __VA_ARGS__)>>::value;         \
1656     };                                                                                                                 \
1657                                                                                                                        \
1658     /* Trivial constuctor */                                                                                           \
1659     CLASS()                                                                                                            \
1660         : mem_(nullptr),                                                                                               \
1661           elements_(0),                                                                                                \
1662           byteSize_(0),                                                                                                \
1663           _ITERATE_ON_ALL_COMMA(_DECLARE_MEMBER_TRIVIAL_CONSTRUCTION, ~, __VA_ARGS__) {}                               \
1664                                                                                                                        \
1665     /* Constructor relying on user provided storage (implementation shared with ROOT streamer) */                      \
1666     SOA_HOST_ONLY CLASS(std::byte* mem, size_type elements) : mem_(mem), elements_(elements), byteSize_(0) {           \
1667       organizeColumnsFromBuffer();                                                                                     \
1668     }                                                                                                                  \
1669                                                                                                                        \
1670     /* Explicit copy constructor and assignment operator */                                                            \
1671     SOA_HOST_ONLY CLASS(CLASS const& _soa_impl_other)                                                                  \
1672         : mem_(_soa_impl_other.mem_),                                                                                  \
1673           elements_(_soa_impl_other.elements_),                                                                        \
1674           byteSize_(_soa_impl_other.byteSize_),                                                                        \
1675           _ITERATE_ON_ALL_COMMA(_DECLARE_MEMBER_COPY_CONSTRUCTION, ~, __VA_ARGS__) {}                                  \
1676                                                                                                                        \
1677     SOA_HOST_ONLY CLASS& operator=(CLASS const& _soa_impl_other) {                                                     \
1678         mem_ = _soa_impl_other.mem_;                                                                                   \
1679         elements_ = _soa_impl_other.elements_;                                                                         \
1680         byteSize_ = _soa_impl_other.byteSize_;                                                                         \
1681         _ITERATE_ON_ALL(_DECLARE_MEMBER_ASSIGNMENT, ~, __VA_ARGS__)                                                    \
1682         return *this;                                                                                                  \
1683     }                                                                                                                  \
1684                                                                                                                        \
1685     SOA_HOST_ONLY void deepCopy(ConstView const& view) {                                                               \
1686       if (elements_ < view.metadata().size())                                                                          \
1687         throw std::runtime_error(                                                                                      \
1688             "In "#CLASS "::deepCopy method: number of elements mismatch ");                                            \
1689       _ITERATE_ON_ALL(_COPY_VIEW_COLUMNS, ~, __VA_ARGS__)                                                              \
1690     }                                                                                                                  \
1691                                                                                                                        \
1692     /* ROOT read streamer */                                                                                           \
1693     template <typename T>                                                                                              \
1694     void ROOTReadStreamer(T & onfile) {                                                                                \
1695       _ITERATE_ON_ALL(_STREAMER_READ_SOA_DATA_MEMBER, ~, __VA_ARGS__)                                                  \
1696     }                                                                                                                  \
1697                                                                                                                        \
1698     /* ROOT allocation cleanup */                                                                                      \
1699     void ROOTStreamerCleaner() {                                                                                       \
1700       /* This function should only be called from the PortableCollection ROOT streamer */                              \
1701       _ITERATE_ON_ALL(_ROOT_FREE_SOA_COLUMN_OR_SCALAR, ~, __VA_ARGS__)                                                 \
1702     }                                                                                                                  \
1703                                                                                                                        \
1704     /* Dump the SoA internal structure */                                                                              \
1705     template <typename T>                                                                                              \
1706     SOA_HOST_ONLY friend void dump();                                                                                  \
1707                                                                                                                        \
1708   private:                                                                                                             \
1709     /* Helper method for the user provided storage constructor and ROOT streamer */                                    \
1710     void organizeColumnsFromBuffer() {                                                                                 \
1711       if constexpr (alignmentEnforcement == cms::soa::AlignmentEnforcement::enforced)                                  \
1712         if (reinterpret_cast<intptr_t>(mem_) % alignment)                                                              \
1713           throw std::runtime_error("In " #CLASS "::" #CLASS ": misaligned buffer");                                    \
1714       auto _soa_impl_curMem = mem_;                                                                                    \
1715       _ITERATE_ON_ALL(_ASSIGN_SOA_COLUMN_OR_SCALAR, ~, __VA_ARGS__)                                                    \
1716       /* Sanity check: we should have reached the computed size, only on host code */                                  \
1717       byteSize_ = computeDataSize(elements_);                                                                          \
1718       if (mem_ + byteSize_ != _soa_impl_curMem)                                                                        \
1719         throw std::runtime_error("In " #CLASS "::" #CLASS ": unexpected end pointer.");                                \
1720     }                                                                                                                  \
1721                                                                                                                        \
1722     /* Helper function to compute the total number of methods */                                                       \
1723     static constexpr std::pair<size_type, size_type> computeMethodsNumber() {                                          \
1724       size_type _soa_methods_count = 0;                                                                                \
1725       size_type _soa_const_methods_count = 0;                                                                          \
1726                                                                                                                        \
1727       _ITERATE_ON_ALL(_COUNT_SOA_METHODS, _soa_methods_count, __VA_ARGS__)                                             \
1728       _ITERATE_ON_ALL(_COUNT_SOA_CONST_METHODS, _soa_const_methods_count, __VA_ARGS__)                                 \
1729                                                                                                                        \
1730       return {_soa_methods_count, _soa_const_methods_count};                                                           \
1731     }                                                                                                                  \
1732                                                                                                                        \
1733     /* compile-time error launched if more than one macro for methods is declared */                                   \
1734     static_assert(computeMethodsNumber().first <= 1,                                                                   \
1735                   "There can be at most one SOA_ELEMENT_METHODS macro."                                                \
1736                   "Please declare all your methods inside the same macro.");                                           \
1737                                                                                                                        \
1738     static_assert(computeMethodsNumber().second <= 1,                                                                  \
1739                   "There can be at most one SOA_CONST_ELEMENT_METHODS macro."                                          \
1740                   "Please declare all your methods inside the same macro.");                                           \
1741                                                                                                                        \
1742     /* Data members */                                                                                                 \
1743     std::byte* mem_ EDM_REFLEX_TRANSIENT;                                                                              \
1744     size_type elements_;                                                                                               \
1745     size_type const scalar_ = 1;                                                                                       \
1746     byte_size_type byteSize_ EDM_REFLEX_TRANSIENT;                                                                     \
1747     _ITERATE_ON_ALL(_DECLARE_SOA_DATA_MEMBER, ~, __VA_ARGS__)                                                          \
1748     /* Making the code conditional is problematic in macros as the commas will interfere with parameter lisings     */ \
1749     /* So instead we make the code unconditional with paceholder names which are protected by a private protection. */ \
1750     /* This will be handled later as we handle the integration of the view as a subclass of the layout.             */ \
1751   };
1752 // clang-format on
1753 
1754 #endif  // DataFormats_SoATemplate_interface_SoALayout_h