#pragma once

#include <cstddef>
#include <type_traits>

namespace psemek::math
{

	namespace detail
	{

		template <typename T>
		struct swizzle_rebind;

		template <template <typename, std::size_t> typename C, typename T, std::size_t N>
		struct swizzle_rebind<C<T, N>>
		{
			template <std::size_t M>
			using type = C<T, M>;
		};

	}

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"

	template <int ... I>
	constexpr auto swizzle = [](auto const & x){
		static_assert(((I == -1 || I < std::decay_t<decltype(x)>::static_dimension) && ...));
		using result = typename detail::swizzle_rebind<std::decay_t<decltype(x)>>::template type<sizeof...(I)>;
		using element = std::decay_t<decltype(x[0])>;
		return result{(I == (-1) ? element{} : x[I])...};
	};

#pragma GCC diagnostic pop

}
