代码之家  ›  专栏  ›  技术社区  ›  user2052436

返回固定大小的数组

c++
  •  1
  • user2052436  · 技术社区  · 8 月前

    如果我有一个固定大小的二维数组 T array[M][N] , 我可以通过以下方式访问元素 array[i][j] ,以及 assert(sizeof(array[i]) == N * sizeof(T)) .

    如何对封装在结构体中的数组执行此操作?

    以下代码允许通过以下方式访问元素 数组[i][j] 但这一断言失败了。

    有办法吗 operator[] 返回 T[N] 而不是 T* ?

    template<class T, int M, int N>
    struct Array
    {
        T data[M][N];
    
    //  constexpr T[N] operator[] (int i) - CANNOT RETURN T[N]!
        constexpr T* operator[] (int i)
        {
            return data[i];
        }
    }
    
    2 回复  |  直到 8 月前
        1
  •  5
  •   Ben Voigt    8 月前

    返回对数组的引用会得到 sizeof 您正在寻找:

    template<class T, int M, int N>
    struct Array
    {
        T data[M][N];
    
    //  constexpr T[N] operator[] (int i) - CANNOT RETURN T[N]!
        constexpr T (&operator[](int i))[N]
        {
            return data[i];
        }
    };
    
    int main()
    {
        Array<double, 2, 3> a;
        std::cout << sizeof(a) << ", " << sizeof(a[1]);
    }
    

    引入类型别名使阅读更容易

    using row = T[N]; // or typedef T (&row)[N]
    
    constexpr row& operator[](int i)
    {
        return data[i];
    }
    
        2
  •  0
  •   Pepijn Kramer    8 月前

    或者你可以制作一个这样的包装: (一般来说,在C++中,不需要使用sizeof那么多,特别是不需要验证数组大小)

    #include <array>
    #include <stdexcept>
    #include <iostream>
    
    template<typename T, std::size_t ROWS, std::size_t COLS>
    class array2d_t final
    {
    public:
        array2d_t() = default;
        ~array2d_t() = default;
    
        array2d_t(const array2d_t&) = default;
        array2d_t& operator=(const array2d_t&) = default;
        array2d_t(array2d_t&&) = default;
        array2d_t& operator=(array2d_t&&) = default;
    
        explicit array2d_t(const int (&values)[ROWS][COLS]) 
        {
            std::size_t offset{0};
            for(std::size_t row{0ul}; row < ROWS; ++row)
            {
                for(std::size_t col{0ul}; col < COLS; ++col, ++offset)
                {
                    m_values[offset] = values[row][col];
                }
            }
        }
    
        auto& at(std::size_t row, std::size_t col)
        {
            if ((row >= ROWS) || (col >= COLS)) throw std::invalid_argument{ "index out of range" };
            std::size_t offset = (COLS*row) + col;
            return m_values[offset];
        }
    
        const auto& operator()(std::size_t row, std::size_t col) const noexcept
        {
            std::size_t offset = (COLS*row) + col;
            return m_values[offset];
        }
    
        const auto& at(std::size_t row, std::size_t col) const
        {
            if ((row >= ROWS) || (col >= COLS)) throw std::invalid_argument{ "index out of range" };
            return operator()(row,col);
        }
    
        constexpr std::size_t rows() const noexcept { return ROWS;};
        constexpr std::size_t columns() const noexcept { return COLS;};
    
    private:
        std::array<T,ROWS*COLS> m_values;
    };
    
    
    int main()
    {
        array2d_t<int,2,2> matrix{{{0,1},{2,3}}};
    }