You can make it work but there are several things that must be considered.
vals
can be passed as a non-type parameter. However, it needs to come after T
. Otherwise, the fundamental type of the parameter is not known.
As a consequence, there is no default value of T
. You could potentially continue to have default value of T
as double
and default value of the last argument as nullptr
but that leads to messy code.
Definition of id_3by3
needs to use &vals
, not just vals
.
If you define vals
to be const
, then the non-type template parameter must also use const
in its type.
const int vals[3][3] { ... };
mandates that you use
template <std::size_t r, std::size_t c, class T, T const(*v)[r][c] >
class abstract_matrix { ... };
If you would like to be able to modify the contents of the matrix, you need to use:
template <std::size_t r, std::size_t c, class T, T (*v)[r][c]>
class abstract_matrix { ... };
which mandates that you use
int vals[3][3] { ... };
Here's a working program:
#include <iostream>
#include <cstdint>
template <std::size_t r, std::size_t c, class T , T (*v)[r][c]>
class abstract_matrix
{
public:
static const std::size_t rows = r;
static const std::size_t cols = c;
typedef T value_type;
constexpr static T(&vals)[r][c] = *v;
constexpr abstract_matrix()
{
}
};
int vals[3][3] {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
using id_3by3 = abstract_matrix<3, 3, int, &vals>;
int main()
{
id_3by3 mymatrix;
// Original matrix.
for ( size_t i = 0; i < id_3by3::rows; ++i )
{
for ( size_t j = 0; j < id_3by3::cols; ++j )
{
std::cout << id_3by3::vals[i][j] << " ";
id_3by3::vals[i][j]++;
}
std::cout << "\n";
}
std::cout << "\n";
// Modified matrix.
for ( size_t i = 0; i < id_3by3::rows; ++i )
{
for ( size_t j = 0; j < id_3by3::cols; ++j )
{
std::cout << id_3by3::vals[i][j] << " ";
}
std::cout << "\n";
}
}
Output:
1 0 0
0 1 0
0 0 1
2 1 1
1 2 1
1 1 2
Update, in response to OP's commment
You can put use static int vals[3][3] = { ... };
when you want to be able define the type a .h file and use it in multiple .cpp files.
I was able to use a .h file with the following content in multiple .cpp files.
#pragma once
#include <cstdint>
template <std::size_t r, std::size_t c, class T , T (*v)[r][c]>
class abstract_matrix
{
public:
static const std::size_t rows = r;
static const std::size_t cols = c;
typedef T value_type;
constexpr static T(&vals)[r][c] = *v;
constexpr abstract_matrix()
{
}
};
static int vals[3][3] {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
using id_3by3 = abstract_matrix<3, 3, int, &vals>;
That can still be improved by dividing those lines into two .h files. E.g., you could use:
abstract_matrix.h:
#pragma once
#include <cstdint>
template <std::size_t r, std::size_t c, class T , T (*v)[r][c]>
class abstract_matrix
{
public:
static const std::size_t rows = r;
static const std::size_t cols = c;
typedef T value_type;
constexpr static T(&vals)[r][c] = *v;
constexpr abstract_matrix()
{
}
};
id_3by3.h:
#include "abstract_matrix.h"
static int vals[3][3] {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
using id_3by3 = abstract_matrix<3, 3, int, &vals>;
That will allow you to define other types similar to id_3by3
in different .h files without needing to duplicate the definition of abstract_matrix
in all of them.