An important design goal of Boost QVM is that it works seamlessly with 3rd-party quaternion, matrix and vector types and libraries. Even when such libraries overload the same C++ operators as Boost QVM, it is usually safe to bring the entire boost::qvm namespace in scope by specifying:
using namespace boost::qvm;
Usually, the above using directive does not introduce ambiguities with function and operator overloads a 3rd-party library may define because:
Bringing the boost::qvm namespace in scope lets you mix vector and matrix types that come from different APIs into a common, type-safe framework. In this case however, it should be considered what types should be returned by binary operations that return an object by value. For example, if you multiply a 3x3 matrix m1 of type user_matrix1 by a 3x3 matrix m2 of type user_matrix2, what type should that operation return?
The answer is that by default, Boost QVM returns some kind of compatible matrix type, so (in C++0x terms) it is always safe to write:
auto m = m1 * m2;
However, the type deduced by default converts implicitly to any compatible matrix type, so the following is also valid, at the cost of a temporary:
user_matrix1 m = m1 * m2;
While the temporary object can be optimized away by many compilers, it can be avoided altogether by specializing the deduce_m2 template. For example, to specify that multiplying a user_matrix1 by a user_matrix2 should always produce a user_matrix1 object, you could specify:
namespace
boost
{
namespace
qvm
{
template <>
struct deduce_m2<user_matrix1,user_matrix2,3,3>
{ typedef user_matrix1 type; };
template <>
struct deduce_m2<user_matrix2,user_matrix1,3,3>
{ typedef user_matrix1 type; };
}
}
Finally, any time you need to create a matrix of a particular C++ type from any other compatible matrix type, you can use the make function:
user_matrix2 m=make<user_matrix2>(m1 * m2);
Perhaps surprisingly, unary operations that return an object by value have a similar, though simpler issue. That's because the argument they're called with may not be copyable, as in:
float m[3][3];
auto inv = inverse(m);
Again, Boost QVM "just works", returning an object of suitable matrix type that is copyable. This deduction process can also be controlled, by specializing the deduce_m template.
Note: Bringing the entire boost::qvm namespace in scope may introduce ambiguities when accessing types defined in 3rd-party libraries. In that case, you can safely bring namespace boost::qvm::sfinae in scope instead, which contains only function and operator overloads that use SFINAE.
Tutorial: Quaternion, Vector and Matrix Types | C Arrays | Views | Swizzling | Interoperability | Back to Boost QVM