问题
Can I define in C++ an array operator that takes multiple arguments? I tried it like this:
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];
}
But I'm getting this error:
error C2804 binary operator '[' has too many parameters
回答1:
Nope, you can't overload operator[]
to accept multiple arguments. You instead can overload operator()
. See How do I create a subscript operator for a Matrix class? from the C++ FAQ.
回答2:
It is not possible to overload the []
operator to accept multiple arguments, but an alternative is to use the proxy pattern.
In two words: a[x][y]
, the first expression (a[x]
) would return a different type, named proxy type, which would have another operator[]
. It would call something like _storedReferenceToOriginalObject->At(x,y)
of the original class.
You will not be able to do a[x,y]
, but I guess you wanted to overload the usual C++-style 2D array syntax anyway.
回答3:
There's a nice little trick you can do with the uniform initialization syntax available in C++11. Instead of taking the index directly, you take a 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];
}
And then use the new syntax:
my_array<int> arr;
// ...
arr[{1, 2, 3}] = 42;
回答4:
For completeness sake: There is a way to actually use the bracket operator with multiple arguments, if they are not basic data types, namely by overloading the comma operator and not the bracket operator, see the following post about comma overloading:
https://stackoverflow.com/a/18136340/5836981
Disclaimer: in my opinion overloading the comma operator is error prone and renders code more obscure, and is worth considering only in more exotic cases. I added this answer because I came over an instance of this in some code and it took me a while to figure out that the key was not the [] operator (which cannot be overloaded with multiple arguments) but the ,operator.
回答5:
N-dimensional arrays of arbitrary type and size in C++:
This answer is inspired by the answer of Pavel Radzivilovsky, thanks for that. I had a bit of a hard time realizing the implementation, as it was my first stab at recursive templates. I'd like to share what I have done such that others can understand more quickly than I did.
I have written a c++ template class to create a n-dimensional array of arbitrary type and size. It needs to be instantiated with the array type and the number of dimensions. The size can be changed dynamically. I've given below a bare (stripped) working version of how to create a multidimensional array of which the elements can be accessed through successive application of the operator[] (e.g. array[x][y][z]). This version can only handle arrays of dimension n>1. The main function shows how to create a 4-dimensional array of integers as an example.
EDIT: keep in mind that the example below is minimal for readability, in that it does not deallocate the array, nor does it do bounds checking on access. Adding this is trivial, and left to the programmer.
#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.
来源:https://stackoverflow.com/questions/1936399/c-array-operator-with-multiple-arguments