C ++ [] оператор массива с несколькими аргументами? - PullRequest
49 голосов
/ 20 декабря 2009

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

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

Ответы [ 5 ]

44 голосов
/ 20 декабря 2009

Нет, вы не можете перегрузить operator[], чтобы принять несколько аргументов. Вместо этого вы можете перегрузить operator(). См. Как мне создать оператор индекса для класса Matrix? из C ++ FAQ.

40 голосов
/ 20 декабря 2009

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

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

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

36 голосов
/ 10 декабря 2014

Есть хороший маленький трюк, который вы можете сделать с помощью единого синтаксиса инициализации, доступного в C ++ 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;
10 голосов
/ 02 февраля 2017

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

https://stackoverflow.com/a/18136340/5836981

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

2 голосов
/ 13 августа 2014

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

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

Я написал шаблонный класс c ++ для создания n-мерного массива произвольного типа и размера. Его необходимо создать с типом массива и количеством измерений. Размер может быть изменен динамически. Ниже я привел голую (раздетую) рабочую версию того, как создать многомерный массив, доступ к элементам которого можно получить с помощью последовательного применения оператора [] (например, array [x] [y] [ г]). Эта версия может работать только с массивами измерения 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;
}

Наслаждайтесь.

...