簡體   English   中英

如何使用二維數組作為模板參數?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM