[英]How to use 2-dimensional array as template argument?
我想將二維數組作為參數傳遞給模板 function,而不指定維度且不使用宏。 這是演示我想要什么的代碼。 重要的一點是靠近中間的makeHow()
方法,並在最后調用它。
如何使Matrix::makeHow()
方法正常工作?
#include <algorithm>
#include <iostream>
#include <memory>
#include <ostream>
class Matrix {
int rows = 0;
int cols = 0;
std::unique_ptr<double> data{};
friend std::ostream &operator<<(std::ostream &stream, const Matrix &m);
public:
// just example: this works but is inconvenient
template<class ARRAY>
static Matrix make(int rows, ARRAY *source)
{
Matrix m;
m.cols = sizeof(*source)/ sizeof(**source);
m.rows = rows;
m.data.reset(new double[m.rows * m.cols]);
std::copy(&(source[0][0]), &(source[0][0]) + (m.rows*m.cols), m.data.get());
std::cout << __PRETTY_FUNCTION__ << ": rows * cols = " << m.rows << " * " << m.cols << std::endl;
return m;
}
// just example: this works but is inconvenient, too
template<int ROWS, class ARRAY>
static Matrix make(ARRAY *source)
{
Matrix m;
m.cols = sizeof(*source)/ sizeof(**source);
m.rows = ROWS;
m.data.reset(new double[m.rows * m.cols]);
std::copy(&(source[0][0]), &(source[0][0]) + (m.rows*m.cols), m.data.get());
std::cout << __PRETTY_FUNCTION__ << ": rows * cols = " << m.rows << " * " << m.cols << std::endl;
return m;
}
// THE IMPORTANT PART: this doesn't work, sizeof(ARRAY) is size of pointer
template<class ARRAY>
static Matrix makeHow(ARRAY *source)
{
Matrix m;
m.cols = sizeof(*source)/ sizeof(**source);
m.rows = sizeof(ARRAY) / sizeof(*source);
m.data.reset(new double[m.rows * m.cols]);
std::copy(&(source[0][0]), &(source[0][0]) + (m.rows*m.cols), m.data.get());
std::cout << __PRETTY_FUNCTION__ << ": rows * cols = " << m.rows << " * " << m.cols << std::endl;
return m;
}
};
// Convenience macro, has all the ugly macro problems, but works...
#define make_matrix(array) Matrix::make<sizeof(array)/sizeof(*array)>(array)
std::ostream &operator<<(std::ostream &stream, const Matrix &m)
{
for(int row = 0; row < m.rows; ++row) {
for(int col = 0; col < m.cols; ++col) {
auto index = row * m.cols + col;
stream << m.data.get()[index] << ' ';
}
stream << '\n';
}
return stream;
}
int main()
{
double data[][2] = { {1.1, 1.2},
{2.1, 2.2},
{3.1, 3.2} };
constexpr int ROWS = sizeof(data)/sizeof(*data);
std::cout << "\nUsing explicit syntax 1:\n" << Matrix::make(ROWS, data);
std::cout << "\nUsing explicit syntax 2:\n" << Matrix::make<ROWS>(data);
std::cout << "\nUsing #define macro:\n" << make_matrix(data);
std::cout << "\nUsing broken function:\n" << Matrix::makeHow(data); // HOW TO MAKE THIS WORK?
}
這產生了 output
Using explicit syntax 1:
static Matrix Matrix::make(int, ARRAY*) [with ARRAY = double [2]]: rows * cols = 3 * 2
1.1 1.2
2.1 2.2
3.1 3.2
Using explicit syntax 2:
static Matrix Matrix::make(ARRAY*) [with int ROWS = 3; ARRAY = double [2]]: rows * cols = 3 * 2
1.1 1.2
2.1 2.2
3.1 3.2
Using #define macro:
static Matrix Matrix::make(ARRAY*) [with int ROWS = 3; ARRAY = double [2]]: rows * cols = 3 * 2
1.1 1.2
2.1 2.2
3.1 3.2
Using broken function:
static Matrix Matrix::makeHow(ARRAY*) [with ARRAY = double [2]]: rows * cols = 1 * 2
1.1 1.2
要將數組作為模板項傳遞,您還需要對維度進行模板化:
template <typename T, std::size_t N>
void f( T (&xs)[ N ] )
{
for (auto x : xs)
...
}
對於二維數組,您只需要添加另一個維度:
template <typename T, std::size_t R, std::size_t C>
void f( T (&xs)[ R ][ C ] )
{
for (auto & row : xs)
for (auto x : row)
...
}
但是請記住,您擁有的每個不同的數組都會在您的可執行文件中生成一個新的 function。 我更喜歡使用模板化的東西來生成內聯函數,以與更原始的低級 function 接口,它適用於一維數組,但知道如何計算每一行和每一列的索引(因為模板沿着數組的維度傳遞) . 這樣,只有更原始的版本會創建代碼,而內聯模板函數會消失。
template<class ARRAY>
static Matrix makeHow(ARRAY & source)
// ^
// |
// |
// +---------------------+
// | this one right here |
// +---------------------+
{
Matrix m;
m.rows = sizeof(source) / sizeof(*source);
m.cols = sizeof(*source) / sizeof(**source);
... etc
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.