#pragma once #include namespace sp { /// @brief Default case, see field_index specialization for implementation details template typename U, typename = void> static constexpr size_t field_index = 0; /// @brief A templated size_t that counts the number of existing classes U with a "field_name" member /// @tparam N Current counter for recursion (user should always call it with 0) /// @tparam T Can be any type, must be different for each field we want to be counted later (used because we can't have a empty /// template<> specialization nested in a class) /// @tparam U The templated class that will be searched for match template typename U> static constexpr size_t field_index::field_name)>> = 1 + field_index; /// @brief Concat multiple tuples in one big tuple /// @tparam ...input_t Multiple std::tuple types to concat template using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); template constexpr bool tuple_contains_type = false; template constexpr bool tuple_contains_type> = std::disjunction_v...>; template constexpr int get_tuple_index = 0; template constexpr int get_tuple_index> = 0; template constexpr int get_tuple_index> = 1 + get_tuple_index>; // Template black magic to loop at compile time template void loop_impl(std::index_sequence, LoopBody&& loop_body) { (loop_body(std::integral_constant{}), ...); } template void loop(LoopBody&& loop_body) { loop_impl(std::make_index_sequence{}, std::forward(loop_body)); } namespace details { template class TupleForEachHelper { public: template static void exec(TTuple&& tuple, TFunc&& func) { using Tuple = typename std::decay::type; static const std::size_t TupleSize = std::tuple_size::value; static_assert(TRem <= TupleSize, "Incorrect parameters"); // Invoke function with current element static const std::size_t Idx = TupleSize - TRem; func(std::get(std::forward(tuple))); // Compile time recursion - invoke function with the remaining elements TupleForEachHelper::exec(std::forward(tuple), std::forward(func)); } }; template <> class TupleForEachHelper<0> { public: // Stop compile time recursion template static void exec(TTuple&& tuple, TFunc&& func) { static_cast(tuple); static_cast(func); } }; } // namespace details template void tupleForEach(TTuple&& tuple, TFunc&& func) { using Tuple = typename std::decay::type; static const std::size_t TupleSize = std::tuple_size::value; details::TupleForEachHelper::exec(std::forward(tuple), std::forward(func)); } } // namespace sp