added structured binding support for vector

This commit is contained in:
Hartmut Seichter 2024-07-14 22:38:13 +02:00
parent a5d42995b2
commit 98685e49ed
2 changed files with 40 additions and 13 deletions

View file

@ -26,6 +26,8 @@
#include <pw/core/globals.hpp>
#include <cmath>
#include <concepts>
#include <functional>
namespace pw {
@ -38,7 +40,7 @@ concept Vector3 = (N == 3);
template <typename T, auto N>
concept Vector4 = (N == 4);
template <typename Scalar, unsigned int N> struct vector final {
template <typename Scalar, std::size_t N> struct vector {
using value_type = Scalar;
using size_type = decltype(N);
@ -56,7 +58,7 @@ template <typename Scalar, unsigned int N> struct vector final {
return std::forward<decltype(self)>(self).v_;
}
auto&& operator[](this auto&& self, unsigned int e) {
auto&& operator[](this auto&& self, size_type e) {
return std::forward<decltype(self)>(self).v_[e];
}
@ -99,8 +101,8 @@ template <typename Scalar, unsigned int N> struct vector final {
}(std::make_index_sequence<N>{});
}
static constexpr auto lerp(const vector& A, const vector& B,const Scalar& factor) -> vector
{
static constexpr auto lerp(const vector& A, const vector& B,
const Scalar& factor) -> vector {
return [&]<std::size_t... Ss>(std::index_sequence<Ss...>) {
return vector<Scalar, N>{{A[Ss] + factor * (B[Ss] - A[Ss])...}};
}(std::make_index_sequence<N>{});
@ -183,9 +185,7 @@ template <typename Scalar, unsigned int N> struct vector final {
(*this)[0] * rhs[1] - rhs[0] * (*this)[1]};
}
constexpr vector normalized() const noexcept {
return (*this) / norm();
}
constexpr vector normalized() const noexcept { return (*this) / norm(); }
auto&& x(this auto&& self)
requires(Vector2<Scalar, N> || Vector3<Scalar, N> || Vector4<Scalar, N>)
@ -254,15 +254,19 @@ template <typename Scalar, unsigned int N> struct vector final {
};
//
// Iterators
// tuple like for structured bindings
//
constexpr const_pointer begin() const {
return &v_[0];
template <size_type idx> auto get(this auto&& self) -> decltype(auto) {
static_assert(idx < N, "out of bounds access to a member.");
return std::forward_like<decltype(self)>(self.v_[idx]);
}
constexpr const_pointer end() const {
return &v_[N];
}
//
// Iterators
//
constexpr const_pointer begin() const { return &v_[0]; }
constexpr const_pointer end() const { return &v_[N]; }
};
// deduction guide for vector
@ -291,4 +295,16 @@ using vector4i = vector4<int>;
} // namespace pw
//
// tuple - protocol
//
template <class Scalar, std::size_t N>
struct std::tuple_size<pw::vector<Scalar, N>>
: std::integral_constant<std::size_t, N> {};
template <std::size_t I, class Scalar, std::size_t N>
struct std::tuple_element<I, pw::vector<Scalar, N>> {
using type = Scalar;
};
#endif

View file

@ -3,6 +3,9 @@
#include <pw/core/vector.hpp>
#include <print>
#include <tuple>
#include <vector>
auto main() -> int {
@ -61,5 +64,13 @@ auto main() -> int {
std::print("{} * {} -> {}\n", pw::serialize::to_string(e1),
pw::serialize::to_string(e2), e1_dot_e2);
auto vec3f = pw::vector{1.f, 2.f, 3.f};
std::print("y: {}\n", vec3f.get<1>());
std::print("tuple size {}\n", std::tuple_size_v<decltype(vec3f)>);
auto& [x, y, z] = vec3f;
std::print("x:{} y:{} z:{}\n", x, y, z);
return 0;
}