Возврат массива фиксированного размера

Если у меня есть двумерный массив фиксированного размера T array[M][N], Я могу получить доступ к элементам через array[i][j] и assert(sizeof(array[i]) == N * sizeof(T)).

Как я могу сделать это для массива, завернутого в структуру?

Следующий код позволяет получать доступ к элементам через array[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];
    }
}

Пробовали вернуть ссылку на массив? Что-то вроде T (&operator[](int i))[N] Он не возвращает значение, но T* также не копирует содержимое среза.

Ben Voigt 27.08.2024 19:48

Вы можете вернуть std::span во внутренний массив.

NathanOliver 27.08.2024 19:50

Вот почему C++ как std::array

Pepijn Kramer 27.08.2024 20:03

Примечание для будущих читателей: помните, что sizeof в указателе всегда указывает размер указателя, а не того, на что он указывает. Указатель знает только, где что-то может быть. Он не знает, действительно ли существует действительный объект или этот объект является массивом.

user4581301 27.08.2024 20:07
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Возврат ссылки на массив дает 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];
}

Или вы можете сделать обертку вот так: (в целом в 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}}};
}

Другие вопросы по теме