Add test for a custom type.

Custom type is implicitly constructible, implicitly castable
to float and can be compared to int.
This commit is contained in:
King_DuckZ 2018-10-30 20:31:49 +00:00
parent 7225298698
commit a4184811b1
2 changed files with 148 additions and 0 deletions

View file

@ -9,6 +9,7 @@ add_executable(${PROJECT_NAME}
test_operators.cpp
test_sequence_range.cpp
test_offset_getters.cpp
test_custom_type.cpp
)
target_link_libraries(${PROJECT_NAME}

View file

@ -0,0 +1,147 @@
/*
* Copyright 2015-2017 Michele "King_DuckZ" Santullo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vectorwrapper/vectorwrapper.hpp"
#include "vectorwrapper/vector_cast.hpp"
#include <gtest/gtest.h>
#include <cstddef>
#include <array>
#include <iostream>
namespace {
int gcd (int a, int b) {
if ((a && b) == false)
return 0;
int r, q, uRet;
do {
uRet = b;
q = a / b;
r = a - q * b;
a = b;
b = r;
} while (r);
return uRet;
}
class Rational {
public:
Rational() = default;
Rational (int num, int den) : m_n(num), m_d(den) {}
Rational (int num) : m_n(num), m_d(1) {}
Rational (const Rational&) = default;
Rational (Rational&&) = default;
~Rational() = default;
Rational& operator= (const Rational&) = default;
Rational& operator= (Rational&&) = default;
bool operator== (const Rational& o) const { return m_n == o.m_n and m_d == o.m_d; }
bool operator== (int o) const { return m_n == o and 1 == m_d; }
operator float() const { return static_cast<float>(m_n) / static_cast<float>(m_d); }
Rational& operator*= (const Rational& o) {
m_n *= o.m_n; m_d *= o.m_d; simplify(); return *this;
}
Rational& operator/= (const Rational& o) {
m_n *= o.m_d; m_d *= o.m_n; simplify(); return *this;
}
int num() const { return m_n; }
int den() const { return m_d; }
private:
void simplify() { const int t = gcd(m_n, m_d); m_n /= t; m_d /= t; }
int m_n, m_d;
};
bool operator== (int a, const Rational& b) {
return a == b.num() and b.den() == 1;
}
Rational operator* (Rational a, const Rational& b) { a *= b; return a; }
Rational operator/ (Rational a, const Rational& b) { a /= b; return a; }
std::ostream& operator<< (std::ostream& os, const Rational& r) {
os << r.num() << '/' << r.den();
return os;
}
struct ThreeRationals {
Rational a, b, c;
};
} //unnamed namespace
namespace vwr {
template <>
struct VectorWrapperInfo<ThreeRationals> {
enum { dimensions = 3 };
typedef Rational scalar_type;
enum {
offset_x = offsetof(ThreeRationals, a),
offset_y = offsetof(ThreeRationals, b),
offset_z = offsetof(ThreeRationals, c)
};
};
template <>
struct VectorWrapperInfo<std::array<float, 3> > {
enum { dimensions = 3 };
typedef float scalar_type;
static scalar_type& get_at (size_type i, std::array<float, 3>& v) {
return v[i];
}
};
} //namespace vwr
namespace {
typedef vwr::Vec<ThreeRationals> rvec3;
typedef vwr::Vec<std::array<float, 3> > fvec3;
} //unnamed namespace
TEST(vwr, custom_type) {
using vwr::vector_cast;
rvec3 rational3(
Rational(1),
Rational(1, 2),
Rational(1, 3)
);
EXPECT_EQ(1, rational3.x());
EXPECT_EQ(Rational(1, 2), rational3.y());
EXPECT_EQ(Rational(1, 3), rational3.z());
fvec3 float3 = vector_cast<fvec3>(rational3);
EXPECT_EQ(1.0f, float3.x());
EXPECT_EQ(0.5f, float3.y());
rational3 *= 4;
EXPECT_EQ(4, rational3.x());
EXPECT_EQ(2, rational3.y());
EXPECT_EQ(Rational(4, 3), rational3.z());
rational3 /= 2;
EXPECT_EQ(2, rational3.x());
EXPECT_EQ(1, rational3.y());
EXPECT_EQ(Rational(2, 3), rational3.z());
}