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.