Disable implicit conversions by default and update readme.

Implicit conversions are still needed for the old unit test to build.
This commit is contained in:
King_DuckZ 2016-11-02 01:12:00 +01:00
parent 2725d4f63d
commit 6ab4d586eb
3 changed files with 24 additions and 9 deletions

View file

@ -3,8 +3,8 @@
## Motivation ##
### Short version ###
A vector wrapper is mainly useful if used as an adapter between vectors from different libraries. It basically removes the need to explicitly construct a vector of type B when you have a vector of type A.
It's roughly equivalent to using a reinterpret_cast on your vectors, but the code tries really hard to make sure the cast is valid in all cases, wrapping it nicely behind a clean interface. Implicit constructors also allow to convert easily from one type to the other.
A vector wrapper is useful if used as an adapter between vectors from different libraries. It removes the need to explicitly construct a vector of type B when you have a vector of type A.
It's roughly equivalent to using a reinterpret_cast on your vectors, but the code tries really hard to make sure the cast is valid in all cases, wrapping safety checks nicely behind a clean interface. Implicit constructors also allow to convert easily from one type to the other (if enabled at build time).
### Long version ###
We all need vectors in our code, and there are quite a few implementations out there. They all do their job, and in terms of interface they are pretty similar to each other, but not *exactly* the same thing.
@ -27,8 +27,11 @@ Unfortunately the fact that you use `Vec<std::array<float, 3>>` and `Vec<Ogre::V
You still need to type some code in order to get started using the vector wrapper class, which is basically your custom implementation of a struct listing informations about the wrapped type. That's not a lot of code.
## Features ##
### Build time configuration ###
* VWR_WITH_IMPLICIT_CONVERSIONS (default: not defined) Enable implicit conversions between wrappers of vectors of different type (see Automated conversions).
### Automated conversion ###
You can assign or construct a `Vec<A>` from a `Vec<B>`, provided they have the same dimensions and the assignemnt operator is able to convert B's scalar type to that of A.
You can assign or construct a `Vec<A>` from a `Vec<B>`, provided they have the same dimensions and the assignemnt operator is able to convert B's scalar type to that of A. You need to define VWR_WITH_IMPLICIT_CONVERSIONS for this to work.
### Access the wrapped type ###
Through the `data()` method you can always obtain a ref to the wrapped type.

View file

@ -39,8 +39,10 @@ namespace vwr {
define_has_method(get_at, GetAt);
define_has_enum(cast_ignore_trailing_properties, CastIgnoreTrailingProperties);
#if defined(VWR_WITH_IMPLICIT_CONVERSIONS)
template <typename V1, typename V2, std::size_t D>
Vec<V1>& assign ( Vec<V1, D>& parLeft, const Vec<V2, D>& parRight );
#endif
template <typename V>
Vec<V>& assign_same_type ( Vec<V>& parLeft, const Vec<V>& parRight );
@ -318,11 +320,13 @@ namespace vwr {
explicit Vec ( const vector_type& parIn ) : implem::VecBase<V>(parIn) { }
template <typename T>
explicit Vec ( const typename std::enable_if<std::is_same<T, scalar_type>::value and not std::is_same<scalar_type, vector_type>::value, T>::type& parX ) : implem::VecBase<V>(parX) { }
#if defined(VWR_WITH_IMPLICIT_CONVERSIONS)
template <typename V2> Vec ( const Vec<V2, dimensions>& parOther ) { implem::assign(*this, parOther); }
Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); }
template <typename V2>
Vec& operator= ( const Vec<V2, dimensions>& parOther ) { return implem::assign(*this, parOther); }
#endif
Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); }
};
template <typename V>
@ -344,11 +348,13 @@ namespace vwr {
explicit Vec ( const vector_type& parIn ) : implem::VecBase<V>(parIn) { }
explicit Vec ( const scalar_type parX ) : implem::VecBase<V>(parX) { }
Vec ( scalar_type parX, scalar_type parY ) : implem::VecBase<V>(parX, parY) { }
#if defined(VWR_WITH_IMPLICIT_CONVERSIONS)
template <typename V2> Vec ( const Vec<V2, dimensions>& parOther ) { implem::assign(*this, parOther); }
Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); }
template <typename V2>
Vec& operator= ( const Vec<V2, dimensions>& parOther ) { return implem::assign(*this, parOther); }
#endif
Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); }
Vec& operator= ( const vector_type& parOther ) { this->data() = parOther; return *this; }
};
@ -372,11 +378,13 @@ namespace vwr {
explicit Vec ( const vector_type& parIn ) : implem::VecBase<V>(parIn) { }
explicit Vec ( const scalar_type parX ) : implem::VecBase<V>(parX) { }
Vec ( scalar_type parX, scalar_type parY, scalar_type parZ ) : implem::VecBase<V>(parX, parY, parZ) { }
#if defined(VWR_WITH_IMPLICIT_CONVERSIONS)
template <typename V2> Vec ( const Vec<V2, dimensions>& parOther ) { implem::assign(*this, parOther); }
Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); }
template <typename V2>
Vec& operator= ( const Vec<V2, dimensions>& parOther ) { return implem::assign(*this, parOther); }
#endif
Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); }
Vec& operator= ( const vector_type& parOther ) { this->data() = parOther; return *this; }
};

View file

@ -11,3 +11,7 @@ add_executable(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME}
gtest
)
target_compile_definitions(${PROJECT_NAME}
PRIVATE VWR_WITH_IMPLICIT_CONVERSIONS
)