Boost LA

Interoperability

An important design goal of Boost LA is that it works seamlessly with 3rd-party matrix and vector types and libraries. Even when such libraries overload the same C++ operators as Boost LA, it is safe to bring the entire boost::la namespace in scope by specifying:

using namespace boost::la;

This does not cause interference with 3rd-party overloads because:

  • All boost::la function and operator overloads use SFINAE, which makes them disappear unless an expression uses types that have the appropriate Boost LA-specific type traits defined;
  • Whenever Boost LA function or operator overloads are compatible with a given expression, their signature is extremely generic, which means that virtually any other compatible overload will be a better match in any overload resolution.

Bringing the boost::la 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 LA 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 most compilers, it can be avoided altogether by specializing the deduce_matrix2 template. For example, to specify that multiplying user_matrix1 by user_matrix2 should always produce a user_matrix1 object, you could specify:

namespace
boost
    {
    namespace
    la
        {
        template <>
        struct deduce_matrix2<user_matrix1,user_matrix2,3,3>
            { typedef user_matrix1 type; };

        template <>
        struct deduce_matrix2<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 LA "just works", returning an object of suitable matrix type that is copyable. This deduction process can also be controlled, by specializing the deduce_matrix template.


Tutorial: Vector and Matrix Types | C Arrays | Views | Swizzling | Interoperability | Back to Boost LA