Museful - 1 year ago 59

C++ Question

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>

public:

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...

private:

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)`

`col2d v = {v1,v2}`

`buf`

`col2d v = {{v1, v2}}`

`buf`

Any advice?

Answer Source

```
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

```
template<class...Ts,
std::enavle_if_t< (sizeof...(Ts)==N*M), int> =0
>
mat(flat_t, Ts&&...ts):
buf{{std::forward<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.