# QVM: Quaternions, Vectors, Matrices

### vec_traits

#include <boost/qvm/vec_traits.hpp>

    namespace
    boost
    {
        namespace
        qvm
        {
            template <class V>
            struct vec_traits
            {
                /*main template members unspecified*/
            };

            /*
            User-defined (possibly partial) specializations:

            template <>
            struct vec_traits<V>
            {
                static int const dim = /*user-defined*/;
                typedef /*user-defined*/ scalar_type;

                template <int I> static inline scalar_type read_element( Vector const & v );
                template <int I> static inline scalar_type & write_element( Vector & v );

                static inline scalar_type read_element_idx( int i, Vector const & v );
                static inline scalar_type & write_element_idx( int i, Vector & v );
            };
            */
        }
    }

The vec_traits template must be specialized for (user-defined) vector types in order to enable vector and matrix operations defined in Boost QVM headers for objects of those types.

Note: vector types are not required to be copyable.

The main vec_traits template members are not specified. Valid specializations are required to define the following members:

- dim: the expression vec_traits<Vector>::dim must evaluate to a compile-time integer constant greater than 0 that specifies the vector size.
- scalar_type: the expression vec_traits<Vector>::scalar_type must be a value type which satisfies the scalar requirements.

In addition, valid specializations of the vec_traits template may define the following access functions as static members, where v is an object of type Vector, I is a compile-time integer constant, and i is a variable of type int:

- read_element: the expression vec_traits<Vector>::read_element<I>(v) returns either a copy of or a const reference to the I-th element of v.
- write_element: the expression vec_traits<Vector>::write_element<I>(v) returns mutable reference to the I-th element of v.
- read_element_idx: the expression vec_traits<Vector>::read_element_idx(i,v) returns either a copy of or a const reference to the i-th element of v.
- write_element_idx: the expression vec_traits<Vector>::write_element_idx(i,v) returns mutable reference to the i-th element of v.

It is illegal to call any of the above functions unless is_vec<Vector>::value is true. Even then, vector types are allowed to define only a subset of the access functions. The general requirements are:

- At least one of read_element or write_element must be defined;
- If read_element_idx is defined, read_element must also be defined;
- If write_element_idx is defined, write_element must also be defined.

Below is an example of a user-defined 3D vector type, and its corresponding specialization of the vec_traits template:

    #include <boost/qvm/vec_traits.hpp>

    struct float3 { float a[3]; };

    namespace boost
    {
        namespace qvm
        {
            template <>
            struct vec_traits<float3>
            {
                static int const dim=3;
                typedef float scalar_type;

                template <int I> static inline scalar_type & write_element( float3 & v ) { return v.a[I]; }
                template <int I> static inline scalar_type read_element( float3 const & v ) { return v.a[I]; }

                static inline scalar_type & write_element_idx( int i, float3 & v ) { return v.a[i]; } //optional
                static inline scalar_type read_element_idx( int i, float3 const & v ) { return v.a[i]; } //optional
            };
        }
    }

Equivalently, using the vec_traits_defaults template the above can be shortened to:

    namespace boost
    {
        namespace qvm
        {
            template <>
            struct vec_traits<float3>: vec_traits_defaults<float3,float,3>
            {
                template <int I> static inline scalar_type & write_element( float3 & v ) { return v.a[I]; }

                static inline scalar_type & write_element_idx( int i, float3 & v ) { return v.a[i]; } //optional
            };
        }
    }

See also: assign(vec,vec) | boost/qvm/vec_traits.hpp | boost/qvm/vec_traits_array.hpp | cmp(vec,vec) | convert_to(vec) | cross | deduce_vec | deduce_vec2 | dot(vec,vec) | is_vec | mag(vec) | mag_sqr(vec) | normalize(vec) | operator!=(vec,vec) | operator*(mat,vec) | operator*(quat,vec) | operator*(vec,mat) | operator+(vec,vec) | operator+=(vec,vec) | operator-(vec,vec) | operator-=(vec,vec) | operator==(vec,vec) | rot_mat | rot_quat | rotate(mat,vec,scalar) | rotate(quat,vec,scalar) | SFINAE/enable_if | scalar | set_rot(mat,vec,scalar) | set_rot(quat,vec,scalar) | set_zero(vec) | transform_point | transform_vector | View Proxy | vec | vec_traits<V>::read_element | vec_traits<V>::read_element_idx | vec_traits<V>::scalar_type | vec_traits<V>::write_element | vec_traits<V>::write_element_idx | vec_traits<Vector>::dim | vec_traits_defaults