Fix cast<> method.

Add vector_type to is_vec, because vector_type is private
and it couldn't be used in cast. Besides if not is_vec, you can't
expect to find vector_type. The conditional in the cast return type
works like if V2 is not a Vec, you can just use V as the vector_type,
anyways the first is_vec is false so the whole condition is going to
be false anyways, even if it results that V == V.
This commit is contained in:
King_DuckZ 2015-07-25 01:52:27 +02:00
parent 59d8eb43e7
commit e64db02ac3
4 changed files with 79 additions and 32 deletions

View file

@ -43,50 +43,59 @@ namespace vwr {
template <typename V>
Vec<V>& assign_same_type ( Vec<V>& parLeft, const Vec<V>& parRight );
template <typename T, typename U, std::size_t TS=VectorWrapperInfo<T>::dimensions, std::size_t US=VectorWrapperInfo<T>::dimensions> struct have_same_offsets {
template <typename T, typename U, std::size_t TS=VectorWrapperInfo<T>::dimensions, std::size_t US=VectorWrapperInfo<U>::dimensions> struct have_compat_offsets {
enum { value = false };
};
template <typename T, typename U> struct have_same_offsets<T, U, 1, 1> {
template <typename T, typename U> struct have_compat_offsets<T, U, 1, 1> {
enum {
value = (VectorWrapperInfo<T>::offset_x == VectorWrapperInfo<U>::offset_x)
value = true
};
};
template <typename T, typename U> struct have_same_offsets<T, U, 2, 2> {
template <typename T, typename U> struct have_compat_offsets<T, U, 2, 2> {
enum {
value = (VectorWrapperInfo<T>::offset_x == VectorWrapperInfo<U>::offset_x) and
(VectorWrapperInfo<T>::offset_y == VectorWrapperInfo<U>::offset_y)
value =
VectorWrapperInfo<T>::offset_y - VectorWrapperInfo<T>::offset_x ==
VectorWrapperInfo<U>::offset_y - VectorWrapperInfo<U>::offset_x
};
};
template <typename T, typename U> struct have_same_offsets<T, U, 3, 3> {
template <typename T, typename U> struct have_compat_offsets<T, U, 3, 3> {
enum {
value = (VectorWrapperInfo<T>::offset_x == VectorWrapperInfo<U>::offset_x) and
(VectorWrapperInfo<T>::offset_y == VectorWrapperInfo<U>::offset_y) and
(VectorWrapperInfo<T>::offset_z == VectorWrapperInfo<U>::offset_z)
value =
VectorWrapperInfo<T>::offset_y - VectorWrapperInfo<T>::offset_x ==
VectorWrapperInfo<U>::offset_y - VectorWrapperInfo<U>::offset_x and
VectorWrapperInfo<T>::offset_z - VectorWrapperInfo<T>::offset_x ==
VectorWrapperInfo<U>::offset_z - VectorWrapperInfo<U>::offset_x
};
};
template <typename T, typename U> struct have_same_offsets<T, U, 4, 4> {
template <typename T, typename U> struct have_compat_offsets<T, U, 4, 4> {
enum {
value = (VectorWrapperInfo<T>::offset_x == VectorWrapperInfo<U>::offset_x) and
(VectorWrapperInfo<T>::offset_y == VectorWrapperInfo<U>::offset_y) and
(VectorWrapperInfo<T>::offset_z == VectorWrapperInfo<U>::offset_z) and
(VectorWrapperInfo<T>::offset_w == VectorWrapperInfo<U>::offset_w)
value =
VectorWrapperInfo<T>::offset_y - VectorWrapperInfo<T>::offset_x ==
VectorWrapperInfo<U>::offset_y - VectorWrapperInfo<U>::offset_x and
VectorWrapperInfo<T>::offset_z - VectorWrapperInfo<T>::offset_x ==
VectorWrapperInfo<U>::offset_z - VectorWrapperInfo<U>::offset_x and
VectorWrapperInfo<T>::offset_w - VectorWrapperInfo<T>::offset_x ==
VectorWrapperInfo<U>::offset_w - VectorWrapperInfo<U>::offset_x
};
};
template <typename T, typename U>
struct have_same_layout {
struct have_compat_layout {
enum {
value =
HasOffsetXEnum<VectorWrapperInfo<T>>::value and HasOffsetXEnum<VectorWrapperInfo<U>>::value and
VectorWrapperInfo<T>::dimensions == VectorWrapperInfo<U>::dimensions and
have_same_offsets<T, U>::value
static_cast<int>(VectorWrapperInfo<T>::dimensions) ==
static_cast<int>(VectorWrapperInfo<U>::dimensions) and
have_compat_offsets<T, U>::value
};
};
template <typename V> struct is_vec {
typedef void vector_type;
enum { value = false };
};
template <typename V> struct is_vec<Vec<V>> {
typedef V vector_type;
enum { value = true };
};
@ -103,7 +112,7 @@ namespace vwr {
VecBase ( void ) = default;
template <typename T>
explicit VecBase ( const typename std::enable_if<std::is_same<T, scalar_type>::value and not std::is_same<scalar_type, vector_type>::value, T>::type& parInit );
explicit VecBase ( const T& parInit, typename std::enable_if<std::is_same<T, scalar_type>::value and not std::is_same<scalar_type, vector_type>::value, bool>::type=false );
explicit VecBase ( const vector_type& parInit );
template <typename... Args>
VecBase ( scalar_type parX, scalar_type parY, Args... parArgs );
@ -118,9 +127,9 @@ namespace vwr {
const vector_type& data ( void ) const { return m_wrapped; }
template <typename V2>
const typename std::enable_if<is_vec<V2>::value and have_same_layout<V, typename V2::vector_type>::value, V2>::type& cast ( void ) const;
const typename std::enable_if<is_vec<V2>::value and have_compat_layout<V, typename std::conditional<is_vec<V2>::value, typename is_vec<V2>::vector_type, V>::type>::value and sizeof(V2) <= sizeof(V), V2>::type& cast ( void ) const;
template <typename V2>
typename std::enable_if<is_vec<V2>::value and have_same_layout<V, typename V2::vector_type>::value, V2>::type& cast ( void );
typename std::enable_if<is_vec<V2>::value and have_compat_layout<V, typename std::conditional<is_vec<V2>::value, typename is_vec<V2>::vector_type, V>::type>::value and sizeof(V2) <= sizeof(V), V2>::type& cast ( void );
template <typename V2> VecBase& operator+= ( const VecBase<V2>& parOther );
template <typename V2> VecBase& operator-= ( const VecBase<V2>& parOther );

View file

@ -18,18 +18,18 @@ namespace vwr {
namespace implem {
template <typename V>
template <typename T>
VecBase<V>::VecBase (const typename std::enable_if<std::is_same<T, scalar_type>::value and not std::is_same<scalar_type, vector_type>::value, T>::type& parInit) :
m_wrapped(parInit)
{
}
template <typename V>
VecBase<V>::VecBase (const vector_type& parInit) {
VecBase<V>::VecBase (const T& parInit, typename std::enable_if<std::is_same<T, scalar_type>::value and not std::is_same<scalar_type, vector_type>::value, bool>::type) {
for (int z = 0; z < VectorWrapperInfo<V>::dimensions; ++z) {
VecGetter<V>::get_at(m_wrapped, z) = parInit;
}
}
template <typename V>
VecBase<V>::VecBase (const vector_type& parInit) :
m_wrapped(parInit)
{
}
template <typename V>
template <typename... Args>
VecBase<V>::VecBase (scalar_type parX, scalar_type parY, Args... parArgs) {
@ -67,14 +67,18 @@ namespace vwr {
template <typename V>
template <typename V2>
const typename std::enable_if<is_vec<V2>::value and have_same_layout<V, typename V2::vector_type>::value, V2>::type& VecBase<V>::cast() const {
return *reinterpret_cast<const V2*>(this);
const typename std::enable_if<is_vec<V2>::value and have_compat_layout<V, typename std::conditional<is_vec<V2>::value, typename is_vec<V2>::vector_type, V>::type>::value and sizeof(V2) <= sizeof(V), V2>::type& VecBase<V>::cast() const {
return *reinterpret_cast<const V2*>(
reinterpret_cast<const char*>(this) + VectorWrapperInfo<V>::offset_x
);
}
template <typename V>
template <typename V2>
typename std::enable_if<is_vec<V2>::value and have_same_layout<V, typename V2::vector_type>::value, V2>::type& VecBase<V>::cast() {
return *reinterpret_cast<V2*>(this);
typename std::enable_if<is_vec<V2>::value and have_compat_layout<V, typename std::conditional<is_vec<V2>::value, typename is_vec<V2>::vector_type, V>::type>::value and sizeof(V2) <= sizeof(V), V2>::type& VecBase<V>::cast() {
return *reinterpret_cast<V2*>(
reinterpret_cast<char*>(this) + VectorWrapperInfo<V>::offset_x
);
}
template <typename V>

View file

@ -166,6 +166,10 @@ namespace vwr {
//Vector Wrapper debug assertions
static_assert(not implem::HasOffsetXEnum<VectorWrapperInfo<float>>::value, "Should return false");
static_assert(implem::HasOffsetXEnum<VectorWrapperInfo<SimpleVector2>>::value, "Should return true");
static_assert(implem::have_compat_offsets<SimpleVector3, PaddedVector3>::value, "Should be true");
static_assert(implem::have_compat_layout<SimpleVector3, PaddedVector3>::value, "Should be true");
static_assert(implem::is_vec<pvec3>::value, "Should be true");
static_assert(implem::is_vec<svec3>::value, "Should be true");
} //namespace vwr
#endif

View file

@ -1,6 +1,12 @@
#include "sample_vectors.hpp"
#include <gtest/gtest.h>
void test_svec3 (const vwr::svec3& parVec, float parX, float parY, float parZ) {
EXPECT_EQ(parVec.x(), parX);
EXPECT_EQ(parVec.y(), parY);
EXPECT_EQ(parVec.z(), parZ);
}
TEST(vwr, conversion) {
using namespace vwr;
@ -12,5 +18,29 @@ TEST(vwr, conversion) {
static_assert(std::is_same<decltype(s2), svec2>::value, "Expecting svec2");
EXPECT_EQ(s2.x(), s.x());
EXPECT_EQ(s2.y(), 1.0f);
auto s3 = s2.xyn(2.0f);
EXPECT_EQ(s3.x(), s2.x());
EXPECT_EQ(s3.y(), s2.y());
EXPECT_EQ(s3.z(), 2.0f);
const auto s3_copy(s3);
EXPECT_EQ(s3_copy, s3);
}
{
svec3 s3(1.0f);
mvec3 m3(s3);
EXPECT_EQ(m3.x(), 1.0f);
EXPECT_EQ(m3.y(), 1.0f);
EXPECT_EQ(m3.z(), 1.0f);
EXPECT_EQ(m3.data().x, 1.0f);
EXPECT_EQ(m3.data().y, 1.0f);
EXPECT_EQ(m3.data().z, 1.0f);
}
{
pvec3 p3(1.0f, 2.0f, 3.0f);
test_svec3(p3.cast<svec3>(), p3.x(), p3.y(), p3.z());
}
}