我正在尝试获取一段代码,我正在为有趣的工作而写作。基本上我想生成一个类型,在编译时给出:矩阵。
例如,我希望abstract_matrix
类似于以下内容:
template <std::size_t r, std::size_t c, class T = double>
class abstract_matrix
{
public:
static const std::size_t rows = r;
static const std::size_t cols = c;
typedef T value_type;
typedef T storage_type[rows][cols];
constexpr abstract_matrix(storage_type items)
{
// I hope it's not needed
}
storage_type storage;
};
然后,我希望实际上创建带有一些魔力的具体类型,按照以下方式:
constexpr static const int vals[3][3] {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
// do magic here for the vals parameter to make this compile
using id_3by3 = abstract_matrix<3, 3, vals, int>;
// use the generated type
id_3by3 mymatrix;
auto matrix = mymatrix * ...;
您对如何<#34; 注入&#34;有任何建议吗?那些值进入模板并在编译时生成一个合适的类型?该类型中的所有内容均为static
,const
和constexpr
。
谢谢!
答案 0 :(得分:1)
你可以让它发挥作用,但必须考虑几件事。
vals
可以作为非类型参数传递。但是,它需要在T
之后。否则,参数的基本类型是未知的。
因此,没有默认值T
。您可能继续将默认值T
设置为double
,将最后一个参数的默认值设置为nullptr
,但这会导致代码混乱。
id_3by3
的定义需要使用&vals
,而不仅仅是vals
。
如果您将vals
定义为const
,那么非类型模板参数也必须在其类型中使用const
。
const int vals[3][3] { ... };
要求您使用
template <std::size_t r, std::size_t c, class T, T const(*v)[r][c] >
class abstract_matrix { ... };
如果您希望能够修改矩阵的内容,则需要使用:
template <std::size_t r, std::size_t c, class T, T (*v)[r][c]>
class abstract_matrix { ... };
要求您使用
int vals[3][3] { ... };
这是一个工作计划:
#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";
}
}
输出:
1 0 0
0 1 0
0 0 1
2 1 1
1 2 1
1 1 2
更新,以响应OP的提交
当您希望能够定义.h文件的类型并在多个.cpp文件中使用它时,可以使用static int vals[3][3] = { ... };
。
我能够在多个.cpp文件中使用包含以下内容的.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()
{
}
};
static int vals[3][3] {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
using id_3by3 = abstract_matrix<3, 3, int, &vals>;
通过将这些行分成两个.h文件,仍然可以改进。例如,您可以使用:
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>;
这将允许您在不同的.h文件中定义与id_3by3
类似的其他类型,而无需在所有类型中复制abstract_matrix
的定义。