Museful Museful - 11 days ago 7x
C++ Question

How to make my vector class support direct initialization/assignment

My question is surely silly but there are so many holes in my understanding of C++11 and template programming that I don't know how to approach this.

I'm rolling my own very simple linear algebra library:

typedef short index_t;

template<int M, int N, typename T = double>
class mat {
// may want some specialized constructors for mat<1,N,T> and mat<M,1,T>
T& operator()(index_t i, index_t j) {
return buf[i + j*M];
T& operator[](index_t k) { // useful for special cases where matrix is vector
return buf[k];

// etc...

std::array<T, M*N> buf;

typedef mat<2, 1, double> col2d;
typedef mat<3, 1, double> col3d;
typedef mat<1, 2, double> row2d;
typedef mat<1, 3, double> row3d;
typedef mat<2, 2, double> mat2d;
typedef mat<3, 3, double> mat3d;

I just want it to support a way to assign (or at least initialize) vectors (i.e. matrices with a singleton dimension) directly. For examples, I would like to be able to either do
v = col2d(v1,v2)
or at least
col2d v = {v1,v2}
. I have the impression that making
public might allow
col2d v = {{v1, v2}}
but I don't like the idea of exposing
. I'm not keen on writing out a specialized constructor for each (1,N) and each (M,1). I'm trying to keep the library as simple and readable as possible.

Any advice?

mat(std::array<T, M*N>&& buffin):buf(std::move(buffin)){}
mat(std::array<T, M*N> const& buffin):buf(buffin){}

This does not expose buf, but gives you the col3d x = {{{ 1,2,3 }}}; syntax.

It also lets a mat 3d be initialized with a flat buffer. I find this quite useful myself.

I might be tempted to add

struct flat_t{constexpr flat_t(){};};
constexpr flat_t flat{};

Then prepend the array ctors to mat with a flat_t. This prevents accidental implicit conversion, while still alowing return {flat, {{1,2,3}}}; style return.

An alternativd is

  std::enavle_if_t< (sizeof...(Ts)==N*M), int> =0
mat(flat_t, Ts&&...ts):

Which gives you

col2d{flat, 1,2};

as a valid col2d.

Adding a sfinae test that all of the Ts can be converted to T is a next step for this path.