is there a way to pass nested initializer lists in C++11 to construct a 2D matrix?

后端 未结 2 773
日久生厌
日久生厌 2020-12-16 11:46

Imagine you have a simple matrix class

template 
class Matrix {

  T* data;
  size_t row, col;

public:

  Matrix(size_t m, size_t         


        
2条回答
  •  一整个雨季
    2020-12-16 12:42

    The main issue with using initializer lists to tackle this problem, is that their size is not easily accessible at compile time. It looks like this particular class is for dynamic matrices, but if you wanted to do this on the stack (usually for speed/locality reasons), here is a hint at what you need (C++17):

    template
    struct matrix
    {
        template
        constexpr matrix(const elem_t (&...list)[n]) : data{}
        {
            auto pos = &data[0];
            ((pos = std::copy(list, list + n, pos)), ...);
        }
    
        int data[dim...];
    };
    
    template
    matrix(const elem_t (&...list)[n]) -> matrix, sizeof...(n), (n * ...) / sizeof...(n)>;
    

    I had to tackle this same problem in my linear algebra library, so I understand how unintuitive this is at first. But if you instead pass a C-array into your constructor, you will have both type and size information of the values you've passed in. Also take note of the constuctor template argument deduction (CTAD) to abstract away the template arguments.

    You can then create constexpr matrix objects like this (or, leave out constexpr to simply do this at runtime on the stack):

    constexpr matrix mat{ {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
    

    Which will initialize an object at compile time of type:

    const matrix
    

    If C++20 is supported by your compiler, I would recommend adding a "requires" clause to the CTAD to ensure that all sub-arrays are the same size (mathematically-speaking, n1 == n2 == n3 == n4, etc).

提交回复
热议问题