Allow extra casting if users explicitly whitelist them.
They'll have to make VectorTypeInfo<V> inherit from is_castable_to<U> for every U they want the V to be castable to. Note that if they also want U to be castable to V (so the other way around) they'll have to explicitly whitelist that conversion too in VectorTypeInfo<U>.
This commit is contained in:
parent
b7616a4fcf
commit
421e5e2433
2 changed files with 52 additions and 4 deletions
|
@ -134,6 +134,22 @@ namespace vwr {
|
||||||
enum { value = true };
|
enum { value = true };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename V> struct get_wrapped_ifn {
|
||||||
|
typedef V type;
|
||||||
|
};
|
||||||
|
template <typename T> struct get_wrapped_ifn<Vec<T>> {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename V1, typename V2>
|
||||||
|
struct directly_convertible {
|
||||||
|
enum {
|
||||||
|
value =
|
||||||
|
not HasGetAtMethod<VectorWrapperInfo<typename get_wrapped_ifn<V1>::type>>::value and
|
||||||
|
not HasGetAtMethod<VectorWrapperInfo<typename get_wrapped_ifn<V2>::type>>::value
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
class VecBase {
|
class VecBase {
|
||||||
friend Vec<V>& assign_same_type<V> ( Vec<V>& parLeft, const Vec<V>& parRight );
|
friend Vec<V>& assign_same_type<V> ( Vec<V>& parLeft, const Vec<V>& parRight );
|
||||||
|
@ -160,9 +176,14 @@ namespace vwr {
|
||||||
const vector_type& data ( void ) const { return m_wrapped; }
|
const vector_type& data ( void ) const { return m_wrapped; }
|
||||||
|
|
||||||
template <typename V2>
|
template <typename V2>
|
||||||
const typename std::enable_if<is_vec<V2>::value, V2>::type& cast ( void ) const;
|
const typename std::enable_if<is_vec<V2>::value and directly_convertible<V, V2>::value, V2>::type& cast ( void ) const;
|
||||||
template <typename V2>
|
template <typename V2>
|
||||||
typename std::enable_if<is_vec<V2>::value, V2>::type& cast ( void );
|
typename std::enable_if<is_vec<V2>::value and directly_convertible<V, V2>::value, V2>::type& cast ( void );
|
||||||
|
|
||||||
|
template <typename V2>
|
||||||
|
const typename std::enable_if<is_vec<V2>::value and not directly_convertible<V, V2>::value, V2>::type& cast ( void ) const;
|
||||||
|
template <typename V2>
|
||||||
|
typename std::enable_if<is_vec<V2>::value and not directly_convertible<V, V2>::value, V2>::type& cast ( void );
|
||||||
|
|
||||||
template <typename V2> VecBase& operator+= ( const VecBase<V2>& parOther );
|
template <typename V2> VecBase& operator+= ( const VecBase<V2>& parOther );
|
||||||
template <typename V2> VecBase& operator-= ( const VecBase<V2>& parOther );
|
template <typename V2> VecBase& operator-= ( const VecBase<V2>& parOther );
|
||||||
|
@ -330,6 +351,8 @@ namespace vwr {
|
||||||
Vec<typename std::common_type<V1, V2>::type> binary_op ( const Vec<V1>& parLeft, const Vec<V2>& parRight, Op parOp, const Vec<typename std::common_type<V1, V2>::type>& parLastVal, bt::number_seq<size_type, I...> );
|
Vec<typename std::common_type<V1, V2>::type> binary_op ( const Vec<V1>& parLeft, const Vec<V2>& parRight, Op parOp, const Vec<typename std::common_type<V1, V2>::type>& parLastVal, bt::number_seq<size_type, I...> );
|
||||||
} //namespace implem
|
} //namespace implem
|
||||||
|
|
||||||
|
template <typename V> struct is_castable_to { };
|
||||||
|
|
||||||
template <typename V, size_type S>
|
template <typename V, size_type S>
|
||||||
class Vec : public implem::VecBase<V> {
|
class Vec : public implem::VecBase<V> {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace vwr {
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
template <typename V2>
|
template <typename V2>
|
||||||
const typename std::enable_if<is_vec<V2>::value, V2>::type& VecBase<V>::cast() const {
|
auto VecBase<V>::cast() const -> const typename std::enable_if<is_vec<V2>::value and directly_convertible<V, V2>::value, V2>::type& {
|
||||||
static_assert(sizeof(V2) <= sizeof(VecBase<V>) - min_offset<V>::value, "V2 must fit in V starting from the first coordinate");
|
static_assert(sizeof(V2) <= sizeof(VecBase<V>) - min_offset<V>::value, "V2 must fit in V starting from the first coordinate");
|
||||||
static_assert(std::is_standard_layout<V2>::value, "V2 must be a standard layout type");
|
static_assert(std::is_standard_layout<V2>::value, "V2 must be a standard layout type");
|
||||||
static_assert(min_offset<typename is_vec<V2>::vector_type>::value == 0, "V2 must not have any properties before the first coordinate");
|
static_assert(min_offset<typename is_vec<V2>::vector_type>::value == 0, "V2 must not have any properties before the first coordinate");
|
||||||
|
@ -103,7 +103,32 @@ namespace vwr {
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
template <typename V2>
|
template <typename V2>
|
||||||
typename std::enable_if<is_vec<V2>::value, V2>::type& VecBase<V>::cast() {
|
auto VecBase<V>::cast() -> typename std::enable_if<is_vec<V2>::value and directly_convertible<V, V2>::value, V2>::type& {
|
||||||
|
return const_cast<V2&>(const_cast<const VecBase<V>*>(this)->cast<V2>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
auto VecBase<V>::cast() const -> const typename std::enable_if<is_vec<V2>::value and not directly_convertible<V, V2>::value, V2>::type& {
|
||||||
|
static_assert(std::is_standard_layout<V2>::value, "V2 must be a standard layout type");
|
||||||
|
typedef typename is_vec<V2>::vector_type v2_type;
|
||||||
|
static_assert(std::is_base_of<is_castable_to<typename VectorWrapperInfo<v2_type>::vector_type>, VectorWrapperInfo<V>>::value, "Casting for this type has to be explicitly enabled");
|
||||||
|
|
||||||
|
//Assert that V2 won't stomp on part of V's data, unless the user
|
||||||
|
//has explicitly said he doesn't care.
|
||||||
|
static_assert((sizeof(typename VectorWrapperInfo<typename is_vec<V2>::vector_type>::scalar_type) * VectorWrapperInfo<typename is_vec<V2>::vector_type>::dimensions == sizeof(V2)) or
|
||||||
|
IsCastIgnoreTrailingPropertiesSet<typename is_vec<V2>::vector_type>::value,
|
||||||
|
"V2 must not have any properties past the last coordinate");
|
||||||
|
static_assert(alignof(typename VectorWrapperInfo<V>::scalar_type) == alignof(V2), "Casting to V2 would give you a misaligned variable");
|
||||||
|
|
||||||
|
return *reinterpret_cast<const V2*>(
|
||||||
|
reinterpret_cast<const char*>(&(*this)[0])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
template <typename V2>
|
||||||
|
auto VecBase<V>::cast() -> typename std::enable_if<is_vec<V2>::value and not directly_convertible<V, V2>::value, V2>::type& {
|
||||||
return const_cast<V2&>(const_cast<const VecBase<V>*>(this)->cast<V2>());
|
return const_cast<V2&>(const_cast<const VecBase<V>*>(this)->cast<V2>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue