more constexpr

This commit is contained in:
BlackMATov
2020-11-20 23:31:56 +07:00
parent 98b11af392
commit 9c5acfdc1c
2 changed files with 157 additions and 118 deletions

View File

@@ -7,9 +7,6 @@
#pragma once
#include <cstddef>
#include <algorithm>
#include <functional>
#include <iterator>
#include <stdexcept>
#include <type_traits>
@@ -29,100 +26,103 @@ namespace vmath_hpp::detail
template < typename T >
class vec_base<T, 2> {
public:
T x, y;
T data[2];
public:
constexpr vec_base() : x{}, y{} {}
constexpr vec_base() : data{} {}
constexpr explicit vec_base(uninit_t) {}
constexpr explicit vec_base(const T& v)
: x{v}, y{v} {}
: data{v, v} {}
constexpr vec_base(T x, T y)
: x{std::move(x)}, y{std::move(y)} {}
: data{std::move(x), std::move(y)} {}
constexpr explicit vec_base(vec_base<T, 3>&& xy)
: x{std::move(xy.x)} , y{std::move(xy.y)} {}
: data{std::move(xy.x()), std::move(xy.y())} {}
constexpr explicit vec_base(const vec_base<T, 3>& xy)
: x{xy.x} , y{xy.y} {}
: data{xy.x(), xy.y()} {}
constexpr explicit vec_base(vec_base<T, 4>&& xy)
: x{std::move(xy.x)} , y{std::move(xy.y)} {}
: data{std::move(xy.x()), std::move(xy.y())} {}
constexpr explicit vec_base(const vec_base<T, 4>& xy)
: x{xy.x} , y{xy.y} {}
: data{xy.x(), xy.y()} {}
constexpr T* data() noexcept {
return std::addressof(x);
}
constexpr T& x() noexcept { return data[0]; }
constexpr const T& x() const noexcept { return data[0]; }
constexpr const T* data() const noexcept {
return std::addressof(x);
}
constexpr T& y() noexcept { return data[1]; }
constexpr const T& y() const noexcept { return data[1]; }
};
template < typename T >
class vec_base<T, 3> {
public:
T x, y, z;
T data[3];
public:
constexpr vec_base() : x{}, y{}, z{} {}
constexpr vec_base() : data{} {}
constexpr explicit vec_base(uninit_t) {}
constexpr explicit vec_base(const T& v)
: x{v}, y{v}, z{v} {}
: data{v, v, v} {}
constexpr vec_base(T x, T y, T z)
: x{std::move(x)}, y{std::move(y)}, z{std::move(z)} {}
: data{std::move(x), std::move(y), std::move(z)} {}
constexpr explicit vec_base(vec_base<T, 2>&& xy, T z)
: x{std::move(xy.x)} , y{std::move(xy.y)} , z{std::move(z)} {}
: data{std::move(xy.x()), std::move(xy.y()), std::move(z)} {}
constexpr explicit vec_base(const vec_base<T, 2>& xy, T z)
: x{xy.x} , y{xy.y} , z{std::move(z)} {}
: data{xy.x(), xy.y(), std::move(z)} {}
constexpr explicit vec_base(vec_base<T, 4>&& xyz)
: x{std::move(xyz.x)} , y{std::move(xyz.y)} , z{std::move(xyz.z)} {}
: data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z())} {}
constexpr explicit vec_base(const vec_base<T, 4>& xyz)
: x{xyz.x} , y{xyz.y} , z{xyz.z} {}
: data{xyz.x(), xyz.y(), xyz.z()} {}
constexpr T* data() noexcept {
return std::addressof(x);
}
constexpr T& x() noexcept { return data[0]; }
constexpr const T& x() const noexcept { return data[0]; }
constexpr const T* data() const noexcept {
return std::addressof(x);
}
constexpr T& y() noexcept { return data[1]; }
constexpr const T& y() const noexcept { return data[1]; }
constexpr T& z() noexcept { return data[2]; }
constexpr const T& z() const noexcept { return data[2]; }
};
template < typename T >
class vec_base<T, 4> {
public:
T x, y, z, w;
T data[4];
public:
constexpr vec_base() : x{}, y{}, z{}, w{} {}
constexpr vec_base() : data{} {}
constexpr explicit vec_base(uninit_t) {}
constexpr explicit vec_base(const T& v)
: x{v}, y{v}, z{v}, w{v} {}
: data{v, v, v, v} {}
constexpr vec_base(T x, T y, T z, T w)
: x{std::move(x)}, y{std::move(y)}, z{std::move(z)}, w{std::move(w)} {}
: data{std::move(x), std::move(y), std::move(z), std::move(w)} {}
constexpr explicit vec_base(vec_base<T, 2>&& xy, T z, T w)
: x{std::move(xy.x)} , y{std::move(xy.y)} , z{std::move(z)} , w{std::move(w)} {}
: data{std::move(xy.x()), std::move(xy.y()), std::move(z), std::move(w)} {}
constexpr explicit vec_base(const vec_base<T, 2>& xy, T z, T w)
: x{xy.x} , y{xy.y} , z{std::move(z)} , w{std::move(w)} {}
: data{xy.x(), xy.y(), std::move(z), std::move(w)} {}
constexpr explicit vec_base(vec_base<T, 3>&& xyz, T w)
: x{std::move(xyz.x)} , y{std::move(xyz.y)} , z{std::move(xyz.z)} , w{std::move(w)} {}
: data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z()), std::move(w)} {}
constexpr explicit vec_base(const vec_base<T, 3>& xyz, T w)
: x{xyz.x} , y{xyz.y} , z{xyz.z} , w{std::move(w)} {}
: data{xyz.x(), xyz.y(), xyz.z(), std::move(w)} {}
constexpr T* data() noexcept {
return std::addressof(x);
}
constexpr T& x() noexcept { return data[0]; }
constexpr const T& x() const noexcept { return data[0]; }
constexpr const T* data() const noexcept {
return std::addressof(x);
}
constexpr T& y() noexcept { return data[1]; }
constexpr const T& y() const noexcept { return data[1]; }
constexpr T& z() noexcept { return data[2]; }
constexpr const T& z() const noexcept { return data[2]; }
constexpr T& w() noexcept { return data[3]; }
constexpr const T& w() const noexcept { return data[3]; }
};
}
@@ -158,21 +158,20 @@ namespace vmath_hpp
vec(const vec&) = default;
vec& operator=(const vec&) = default;
void fill(const value_type& v) {
std::fill_n(begin(), size(), v);
}
void swap(vec& other) noexcept(std::is_nothrow_swappable_v<T>) {
std::swap_ranges(begin(), end(), other.begin());
for ( std::size_t i = 0; i < Size; ++i ) {
using std::swap;
swap(data[i], other.data[i]);
}
}
constexpr iterator begin() noexcept { return iterator(data()); }
constexpr const_iterator begin() const noexcept { return const_iterator(data()); }
constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); }
constexpr iterator begin() noexcept { return iterator(data); }
constexpr const_iterator begin() const noexcept { return const_iterator(data); }
constexpr const_iterator cbegin() const noexcept { return const_iterator(data); }
constexpr iterator end() noexcept { return iterator(data() + size()); }
constexpr const_iterator end() const noexcept { return const_iterator(data() + size()); }
constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); }
constexpr iterator end() noexcept { return iterator(data + Size); }
constexpr const_iterator end() const noexcept { return const_iterator(data + Size); }
constexpr const_iterator cend() const noexcept { return const_iterator(data + Size); }
constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
@@ -186,21 +185,26 @@ namespace vmath_hpp
constexpr size_type max_size() const noexcept { return Size; }
constexpr bool empty() const noexcept { return !Size; }
constexpr reference operator[](size_type index) noexcept { return data()[index]; }
constexpr const_reference operator[](size_type index) const noexcept { return data()[index]; }
constexpr reference operator[](size_type index) noexcept {
return data[index];
}
constexpr const_reference operator[](size_type index) const noexcept {
return data[index];
}
constexpr reference at(size_type index) {
if ( index >= size() ) {
throw std::out_of_range("vec::at");
if ( index < Size ) {
return data[index];
}
return data()[index];
throw std::out_of_range("vec::at");
}
constexpr const_reference at(size_type index) const {
if ( index >= size() ) {
throw std::out_of_range("vec::at");
if ( index < Size ) {
return data[index];
}
return data()[index];
throw std::out_of_range("vec::at");
}
};
@@ -213,18 +217,31 @@ namespace vmath_hpp
namespace vmath_hpp
{
template < typename T, std::size_t Size >
bool operator==(const vec<T, Size>& l, const vec<T, Size>& r) {
return std::equal(l.begin(), l.end(), r.begin());
constexpr bool operator==(const vec<T, Size>& l, const vec<T, Size>& r) {
for ( std::size_t i = 0; i < Size; ++i ) {
if ( !(l[i] == r[i]) ) {
return false;
}
}
return true;
}
template < typename T, std::size_t Size >
bool operator!=(const vec<T, Size>& l, const vec<T, Size>& r) {
constexpr bool operator!=(const vec<T, Size>& l, const vec<T, Size>& r) {
return !(l == r);
}
template < typename T, std::size_t Size >
bool operator<(const vec<T, Size>& l, const vec<T, Size>& r) {
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
constexpr bool operator<(const vec<T, Size>& l, const vec<T, Size>& r) {
for ( std::size_t i = 0; i < Size; ++i ) {
if ( l[i] < r[i] ) {
return true;
}
if ( r[i] < l[i] ) {
return false;
}
}
return false;
}
}

View File

@@ -4,11 +4,11 @@
* Copyright (C) 2020, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#include <vmath.hpp/vmath.hpp>
#define CATCH_CONFIG_FAST_COMPILE
#include <catch2/catch.hpp>
#include <vmath.hpp/vmath.hpp>
namespace
{
}
@@ -24,34 +24,34 @@ TEST_CASE("vmath/vec") {
SECTION("ctors") {
{
REQUIRE(vec2i().x == 0);
REQUIRE(vec2i().y == 0);
STATIC_REQUIRE(vec2i().x() == 0);
STATIC_REQUIRE(vec2i().y() == 0);
REQUIRE(vec2i(1).x == 1);
REQUIRE(vec2i(1).y == 1);
STATIC_REQUIRE(vec2i(1).x() == 1);
STATIC_REQUIRE(vec2i(1).y() == 1);
REQUIRE(vec2i(1,2).x == 1);
REQUIRE(vec2i(1,2).y == 2);
STATIC_REQUIRE(vec2i(1,2).x() == 1);
STATIC_REQUIRE(vec2i(1,2).y() == 2);
}
{
vec2i v(1,2);
vec2i v2 = v;
REQUIRE(v2 == vec2i(1,2));
constexpr vec2i v(1,2);
constexpr vec2i v2 = v;
STATIC_REQUIRE(v2 == vec2i(1,2));
}
{
vec2i v(1,2);
vec2i v2 = std::move(v);
REQUIRE(v2 == vec2i(1,2));
constexpr vec2i v(1,2);
constexpr vec2i v2 = std::move(v);
STATIC_REQUIRE(v2 == vec2i(1,2));
}
{
REQUIRE(vec2i(vec3i(1,2,3)) == vec2i(1,2));
REQUIRE(vec2i(vec4i(1,2,3,4)) == vec2i(1,2));
STATIC_REQUIRE(vec2i(vec3i(1,2,3)) == vec2i(1,2));
STATIC_REQUIRE(vec2i(vec4i(1,2,3,4)) == vec2i(1,2));
REQUIRE(vec3i(vec2i(1,2),3) == vec3i(1,2,3));
REQUIRE(vec3i(vec4i(1,2,3,4)) == vec3i(1,2,3));
STATIC_REQUIRE(vec3i(vec2i(1,2),3) == vec3i(1,2,3));
STATIC_REQUIRE(vec3i(vec4i(1,2,3,4)) == vec3i(1,2,3));
REQUIRE(vec4i(vec2i(1,2),3,4) == vec4i(1,2,3,4));
REQUIRE(vec4i(vec3i(1,2,3),4) == vec4i(1,2,3,4));
STATIC_REQUIRE(vec4i(vec2i(1,2),3,4) == vec4i(1,2,3,4));
STATIC_REQUIRE(vec4i(vec3i(1,2,3),4) == vec4i(1,2,3,4));
}
}
@@ -70,12 +70,6 @@ TEST_CASE("vmath/vec") {
}
}
SECTION("fill") {
vec2i v(1,2);
v.fill(4);
REQUIRE(v == vec2i(4));
}
SECTION("swap") {
{
vec2i v1(1,2);
@@ -93,12 +87,6 @@ TEST_CASE("vmath/vec") {
}
}
SECTION("data") {
vec2i v(1,2);
REQUIRE(v.data() == &v.x);
REQUIRE(std::as_const(v).data() == &v.x);
}
SECTION("iter") {
{
vec2i v(1,2);
@@ -162,35 +150,69 @@ TEST_CASE("vmath/vec") {
}
SECTION("operator[]") {
REQUIRE(vec2i(1,2).x == 1);
REQUIRE(vec2i(1,2).y == 2);
REQUIRE(vec2i(1,2)[0] == 1);
REQUIRE(vec2i(1,2)[1] == 2);
{
STATIC_REQUIRE(vec2i(1,2).x() == 1);
STATIC_REQUIRE(vec2i(1,2).y() == 2);
STATIC_REQUIRE(vec3i(1,2,3).x() == 1);
STATIC_REQUIRE(vec3i(1,2,3).y() == 2);
STATIC_REQUIRE(vec3i(1,2,3).z() == 3);
STATIC_REQUIRE(vec4i(1,2,3,4).x() == 1);
STATIC_REQUIRE(vec4i(1,2,3,4).y() == 2);
STATIC_REQUIRE(vec4i(1,2,3,4).z() == 3);
STATIC_REQUIRE(vec4i(1,2,3,4).w() == 4);
}
{
STATIC_REQUIRE(vec2i(1,2)[0] == 1);
STATIC_REQUIRE(vec2i(1,2)[1] == 2);
}
{
vec2i v;
v.x() = 1;
v.y() = 2;
REQUIRE(v == vec2i(1,2));
}
{
vec3i v;
v.x() = 1;
v.y() = 2;
v.z() = 3;
REQUIRE(v == vec3i(1,2,3));
}
{
vec4i v;
v.x() = 1;
v.y() = 2;
v.z() = 3;
v.w() = 4;
REQUIRE(v == vec4i(1,2,3,4));
}
}
SECTION("at") {
REQUIRE(vec2i(1,2).at(0) == 1);
REQUIRE(vec2i(1,2).at(1) == 2);
STATIC_REQUIRE(vec2i(1,2).at(0) == 1);
STATIC_REQUIRE(vec2i(1,2).at(1) == 2);
REQUIRE_THROWS_AS(vec2i(1,2).at(2), std::out_of_range);
}
SECTION("operator==/operator!=") {
REQUIRE(vec2i(1,2) == vec2i(1,2));
REQUIRE_FALSE(vec2i(1,2) == vec2i(2,2));
REQUIRE_FALSE(vec2i(1,2) == vec2i(1,3));
STATIC_REQUIRE(vec2i(1,2) == vec2i(1,2));
STATIC_REQUIRE_FALSE(vec2i(1,2) == vec2i(2,2));
STATIC_REQUIRE_FALSE(vec2i(1,2) == vec2i(1,3));
REQUIRE_FALSE(vec2i(1,2) != vec2i(1,2));
REQUIRE(vec2i(1,2) != vec2i(2,2));
REQUIRE(vec2i(1,2) != vec2i(1,3));
STATIC_REQUIRE_FALSE(vec2i(1,2) != vec2i(1,2));
STATIC_REQUIRE(vec2i(1,2) != vec2i(2,2));
STATIC_REQUIRE(vec2i(1,2) != vec2i(1,3));
}
SECTION("operator<") {
REQUIRE_FALSE(vec2i(1,2) < vec2i(1,2));
STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(1,2));
REQUIRE(vec2i(1,1) < vec2i(1,2));
REQUIRE_FALSE(vec2i(1,2) < vec2i(1,1));
STATIC_REQUIRE(vec2i(1,1) < vec2i(1,2));
STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(1,1));
REQUIRE(vec2i(0,3) < vec2i(1,2));
REQUIRE_FALSE(vec2i(1,2) < vec2i(0,3));
STATIC_REQUIRE(vec2i(0,3) < vec2i(1,2));
STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(0,3));
}
}