Skip to content

Latest commit

 

History

History
156 lines (122 loc) · 4.36 KB

File metadata and controls

156 lines (122 loc) · 4.36 KB
Info

Example

[[maybe_unused]] constexpr [:substitute(^std::tuple, {^int, ^float}):] tuple{}; // std::tuple<int, float>

https://godbolt.org/z/T6oxh48dc

Puzzle

  • Can you implement soa_vector with reflection?
template <class T>
class soa_vector; // TODO

int main() {
  struct vec3_t {
      float x, y, z;
  };

  soa_vector<vec3_t> v{};
  v.push_back({.x = 1, .y = 2, .z = 3});
  assert(1 == v[0].x and 2 == v[0].y and 3 == v[0].z);
}

https://godbolt.org/z/TrWYxre8v

Solutions

template<class T>
class soa_vector {
public:
  constexpr void push_back(const T value) {
    v.push_back(value~member_values)...;
  }

  [[nodiscard]] constexpr auto operator[](const auto pos) const {
    return T{v[pos]...};
  }

private:
  std::vector<T~member_types> ...v;
};

int main() {
  struct vec3_t { float x, y, z; };

  soa_vector<vec3_t> v{};
  v.push_back({.x=1, .y=2, .z=3});
  assert(1 == v[0].x and 2 == v[0].y and 3 == v[0].z);
}

https://circle.godbolt.org/z/ojzvKr98q

template <class T>
class soa_vector {
 public:
    constexpr void push_back(const T value) {
      [&, this]<auto... Ns>(std::index_sequence<Ns...>) { (std::get<Ns>(v).push_back(value.[:std::meta::nonstatic_data_members_of(^T)[Ns]:]), ...); }(members);
    }

    [[nodiscard]] constexpr auto operator[](const auto pos) const {
      return [&, this]<auto... Ns>(std::index_sequence<Ns...>) { return T{std::get<Ns>(v)[pos]...}; }(members);
    }

 private:
    template<class... Ts> using vector = std::vector<Ts...>;

    [[nodiscard]] static consteval auto tuple_of_vectors(const auto type) {
        std::vector<std::meta::info> members{};
        for (auto member : nonstatic_data_members_of(type)) {
            members.push_back(substitute(^vector, {type_of(member)})); // with std::vector -> std::vector<float, allocator<_Tp>>
        }
        return substitute(^std::tuple, members); // define_class can also be used instead
    }

    static constexpr auto members = std::make_index_sequence<std::size(std::meta::nonstatic_data_members_of(^T))>{};

    [:tuple_of_vectors(^T):] v;
};

int main() {
  struct vec3_t {
    float x, y, z;
  };

  soa_vector<vec3_t> v{};
  v.push_back({.x = 1, .y = 2, .z = 3});
  assert(1 == v[0].x and 2 == v[0].y and 3 == v[0].z);
}

https://godbolt.org/z/Yvo83bc4d

namespace impl {
template <typename... Ts>
using vector = std::vector<Ts...>;
template <class T>
struct soa_base_t;
consteval auto make_soa_t(std::meta::info type) -> std::meta::info {
    auto members = std::meta::nonstatic_data_members_of(type);
    std::vector<std::meta::nsdm_description> new_members;
    for (const auto& member : members) {
        auto new_type = std::meta::substitute(^vector, {
                                                           std::meta::type_of(member)});
        auto new_member =
            std::meta::nsdm_description(new_type, {.name = std::meta::name_of(member)});
        new_members.push_back(new_member);
    }
    return std::meta::define_class(std::meta::substitute(^soa_base_t,
                                                         {
                                                             type}),
                                   new_members);
}

template <class T>
using soa_t = [:make_soa_t(^T):];
}  // namespace impl

template <class T>
class soa_vector : impl::soa_t<T> {
    constexpr static auto C = std::meta::nonstatic_data_members_of(^T).size();

   public:
    void push_back(const T& value) {
        [&value, this]<auto... Is>(std::index_sequence<Is...>) {
            (this->[:std::meta::nonstatic_data_members_of(^impl::soa_t<T>)[Is]:]
                 .push_back(value.[:std::meta::nonstatic_data_members_of(^T)[Is]:]), ...);
        }(std::make_index_sequence<C>());
    }
    [[nodiscard]] constexpr auto operator[](std::size_t index) const -> T {
        return [&index, this]<auto... Is>(std::index_sequence<Is...>) {
            return T{
                this->[:std::meta::nonstatic_data_members_of(^impl::soa_t<T>)[Is]:].at(index)...};
        }(std::make_index_sequence<C>());
    }
};

https://godbolt.org/z/bddnjsj8M