The quickest way to do what you seem to want (you didn't really specify it in detail) is to let your matrix class template inherit from a storage class template, and to specialize the storage class depending on whether your MPL predicate returns true or false
#include <array>
#include <iostream>
#include <vector>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/comparison.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/logical.hpp>
using namespace boost;
// in C++98, use
// template<int R, int C>
// struct is_runtime_sized: mpl::if<
// ...
// >::type {};
template<int R, int C>
using is_runtime_sized = typename mpl::if_<
mpl::or_<
mpl::equal_to<mpl::int_<R>, mpl::int_<0>>,
mpl::equal_to<mpl::int_<C>, mpl::int_<0>>
>,
mpl::true_, mpl::false_
>::type;
Note that I've eleminated some unnecessary typename
occurances to make the MPL predicate more readable.
template<class T, int R, int C, bool = is_runtime_sized<R, C>::value>
struct MatrixStorage
{
MatrixStorage() = default;
MatrixStorage(int r, int c): data_(r * c) {} // zero-initializes
protected:
std::vector<T> data_;
};
template<class T, int R, int C>
struct MatrixStorage<T, R, C, false>
{
MatrixStorage() = default;
MatrixStorage(int, int): data_{} {} // zero-initializes
protected:
std::array<T, R * C> data_;
};
Here, I've split the implementation of the dynamically and statically stored matrices. The former uses a std::vector
and the latter a std:array
. Similar to Eigen, both have a default constructor, and both also have a constructor taking the matrix dimensions that zero-initializes.
template<class T, int R = 0, int C = 0>
struct Matrix: public MatrixStorage<T, R, C>
{
Matrix() = default;
// In C++98, write:
// Matrix(int r, int c): MatrixStorage<T, R, C>(r, c) {}
using MatrixStorage<T, R, C>::MatrixStorage;
int size() const { return this->data_.size(); }
};
The actual Matrix
class inherits from the MatrixStorage
, and returns a size()
depending on the currently stored data.
int main()
{
Matrix<int> m_dyn(3, 3);
std::cout << m_dyn.size() << "\n"; // 9
Matrix<int, 2, 2> m_stat;
std::cout << m_stat.size() << "\n"; // 4
}
Live Example. As you can see, the dynamically allocated matrix has size 9, and the statically sized one has size 4. Note that there are two small C++11 features in the above code, that you can easily work-around if you are required to use C++11.