Подтвердить что ты не робот

Оператор массива С++ [] с несколькими аргументами?

Могу ли я определить в С++ оператор массива, который принимает несколько аргументов? Я пробовал это следующим образом:

const T& operator[](const int i, const int j, const int k) const{ 
    return m_cells[k*m_resSqr+j*m_res+i];
}

T& operator[](const int i, const int j, const int k){ 
    return m_cells[k*m_resSqr+j*m_res+i];       
}

Но я получаю эту ошибку:

error C2804 binary operator '[' has too many parameters
4b9b3361

Ответ 2

Невозможно перегрузить оператор [], чтобы принять несколько аргументов, но альтернативой является использование прокси-шаблона .

В двух словах: a[x][y], первое выражение (a[x]) вернет другой тип с именем прокси-типа, который будет иметь другой operator[]. Он называет нечто вроде _storedReferenceToOriginalObject->At(x,y) исходного класса.

Вы не сможете сделать a[x,y], но я предполагаю, что вы все равно хотите перегрузить обычный синтаксис 2D-массива в стиле С++.

Ответ 3

Там хороший небольшой трюк, который вы можете сделать с синтаксисом унифицированной инициализации, доступным на С++ 11. Вместо прямого ввода индекса вы берете POD.

struct indices
{
  std::size_t i, j, k;
};

T& operator[](indices idx)
{
  return m_cells[idx.k * m_resSqr + idx.j * m_res + idx.i];
}

И затем используйте новый синтаксис:

my_array<int> arr;
// ...
arr[{1, 2, 3}] = 42;

Ответ 4

Для полноты: существует способ фактически использовать оператор скобки с несколькими аргументами, если они не являются базовыми типами данных, а именно путем перегрузки оператора запятой, а не оператора скобки, см. следующий пост о перегрузке запятой:

fooobar.com/questions/68551/...

Отказ от ответственности:, на мой взгляд, перегрузка оператора запятой подвержена ошибкам и делает код более неясным, и его стоит рассматривать только в более экзотических случаях. Я добавил этот ответ, потому что я нашел экземпляр этого кода в некотором коде, и мне потребовалось некоторое время, чтобы понять, что ключ не был оператором [] (который не может быть перегружен несколькими аргументами), но оператор operator.

Ответ 5

N-мерные массивы произвольного типа и размера в С++:

Этот ответ вдохновлен ответом Павла Радзивиливского, спасибо за это. Мне было трудно реализовать реализацию, так как это был мой первый удар по рекурсивным шаблонам. Я хотел бы поделиться тем, что я сделал, чтобы другие могли понять быстрее, чем я.

Я написал класс шаблона С++ для создания n-мерного массива произвольного типа и размера. Он должен быть создан с типом массива и количеством измерений. Размер можно изменять динамически. Ниже приведена голая (лишенная) рабочая версия того, как создать многомерный массив, к которому можно получить доступ к элементам посредством последовательного применения оператора [] (например, array [x] [y] [z]). Эта версия может обрабатывать только массивы размерности n > 1. Основная функция показывает, как создать в качестве примера 4-мерный массив целых чисел.

EDIT: имейте в виду, что приведенный ниже пример минимален для удобства чтения, поскольку он не освобождает массив и не выполняет проверку границ доступа. Добавление этого тривиально и остается программисту.

#include <stdio.h>
#include <stdlib.h>

template <typename T, int N>
struct array {
    array<T,N>() : data(NULL), offset((int*) malloc(sizeof(int)*N)){}
    array<T,N>(T *data, int *offset) : data(data), offset(offset){}
    array<T,N-1> operator[](int i){return array<T,N-1>(&data[i*offset[N]], offset);}
    bool resize(int *size){
        offset[N-1] = 1;
        int total_size = size[N-1];
        for(int i = N-2; i >= 0; i--){
            total_size *= size[i];
            offset[i] = offset[i+1]*size[i+1];
        }
        return (data = (T*) realloc (data, total_size*sizeof(T)));
    }
    T *data;
    int *offset;
};

template <typename T>
struct array<T,1>{
    array<T,1>(T *data, int *offset) : data(data){}
    T& operator[](int i){return data[i];}
    T *data;
};

int main () {
    array<int, 4> a;

    // create array with dimensions [1][3][3][7]
    int size[4] = { 1, 3, 3, 7 };
    a.resize(size);               

    a[0][1][2][3] = 123;

    return 0;
}

Enjoy.