5

호출 할 때 : a7 [0] [1] [100];연산자 [] 다차원 배열에서 오버로드 C++

연산자 []에서 첫 번째 인덱스 '0'을 얻을 수 있지만 인덱스로서 재귀 적으로 다른 인덱스 값 1과 100을 얻을 수 없습니다. 재귀적인 folowing 인덱스 값을 얻기 위해 어떻게 operator []를 사용할 수 있습니까? 이 3 차원 배열의 예제에서 operator []는 첫 번째 차원 인 '0'에 대해서만 한 번만 호출됩니다.

내 예제 코드 :

typedef array<T, RestD...> OneDimensionDownArrayT; 

에 선

typedef typename array<T, RestD...>::type OneDimensionDownArrayT; 

을 변경 이유 때문에 array<int, 1, 2, 3>::type 동등한 여기에서 오류가 실제로 조금 미묘한입니다

template <class T, unsigned ... RestD> struct array; 

template <class T, unsigned PrimaryD> 
struct array <T, PrimaryD> { 
    typedef T type[PrimaryD]; 

    type data; 

    T& operator[] (unsigned i) { 
     return data[i]; 
    } 
}; 

template <class T, unsigned PrimaryD, unsigned ... RestD> 
struct array <T, PrimaryD, RestD...> { 
    typedef typename array<T, RestD...>::type OneDimensionDownArrayT; 
    typedef OneDimensionDownArrayT type[PrimaryD]; 

    type data; 

    OneDimensionDownArrayT& operator[] (int i) { 
     OneDimensionDownArrayT& a = data[i]; 
     return a; 
    } 
}; 

int main() { 

    array<int, 1, 2, 3> a7 {{{{1, 2, 3},{4, 5, 6}}}}; 
    a7[0][1][2] = 100; //=>won't recursively go through operator[] 
        //I want to recursively obtain 0, 1 and 2 as index values 

    a7[0][1][100] = 100; //also works correctly. 
    std::cout << a7[0][1][100] << std::endl; 

    return 0; 
} 
+0

그래서 무엇이 문제입니까? 어떤 행동을보고 있습니까? 컴파일 오류가 발생하면 어떻게해야합니까? 런타임 동작이란 무엇입니까? 귀하의 컴파일러와 버전은 무엇입니까? 조금 더 많은 정보가 상처를주지는 않습니다. – yzt

+3

당신은 이것을 고려하지 않았습니까? 대신'operator()'오버로드를 사용하십시오. 실제로, 사람들은 다차원 배열로 '연산자'를 구부리기에는 너무 어렵습니다. –

+5

몇 가지 사이드 노트 : [내 Matrix 클래스의 인터페이스가 배열 배열처럼 보이지 않아야하는 이유는 무엇입니까?] (http://www.parashift.com/c++-faq/matrix-array-of-array.html) 그리고 [나는 아직도 그것을 얻지 못한다. Matrix 클래스의 인터페이스가 배열 배열처럼 보이지 않아야하는 이유는 무엇입니까?] (http://www.parashift.com/c++-faq/matrix-c-style-subscript.html) –

답변

1

array<int, 2, 3>::typearray<int, 3>::type이고 이는 01입니다.. 결국 array<int, 1, 2, 3>::OneDimensionDownArrayTint[2][3]과 같습니다. 이것은 실제 int 배열을 반환하기 때문에 오버로드 된 연산자 []에서 한 수준 아래로 내려가는 이유입니다. 당신은 당신의 주요 방법에 추가하여 자신이를 볼 수 있습니다

 auto & e1 = a7[0]; 
     auto & e2 = e1[0]; 
     auto & e3 = e2[1]; 
     auto & e4 = e3[2]; 
     e4 = 100; 

를 대신 한 번에 모든 접근. 그런 다음 디버거를 단계별로 실행하고 e1-e4의 유형을 확인하십시오. e1은 array<int, 2, 3> & 대신 int (&) [2][3] 유형이됩니다.

이들을 스택 대신 힙에 할당하려면 클래스에서 배열 대신 OneDimensionDownArrayT에 대한 포인터를 선언하고 생성자와 배열 할당/할당 해제를 담당 할 desctructor를 정의하십시오. 다음과 같이 보일 수 있습니다.

template <class T, unsigned PrimaryD, unsigned ... RestD> 
    struct array <T, PrimaryD, RestD...> { 
     typedef typename array<T, RestD...>::type OneDimensionDownArrayT; 

     array():data(new OneDimensionDownArrayT[PrimaryD]){} 
     ~array() { 
      delete[] data; 
     } 

     OneDimensionDownArrayT * data; 

     OneDimensionDownArrayT& operator[] (int i) { 
      OneDimensionDownArrayT& a = data[i]; 
      return a; 
     } 
    }; 

또한 클래스의 복사 생성자, 생성자 및 대입 연산자를 정의해야합니다. 이 구현은 스택에서 훨씬 적은 공간을 차지하지만 포인터 자체와 배열 자체를위한 공간이 필요하기 때문에 총 메모리가 전체적으로 약간 더 많습니다.

+0

이 솔루션은 a1 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]과 같은 매우 큰 어레이에서는 비효율적입니다. 모든 객체 내부에 차원 크기가 증가 할 때 메모리 사용량이 커질 때마다 또 다른 배열 객체가 만들어지기 때문입니다. – Alper

+0

당신이 무슨 일을 하든지, 당신은 10을위한 공간을 할당해야합니다! 사물. 스택의 공간이 부족한 경우 힙 (동적으로 메모리를 할당)을 사용해보십시오. – SirGuy

+0

typedef 배열 OneDimensionDownArrayT; 작동하지만 각 차원의 객체 아래에서 객체를 만들고 배열하며 비정상적인 메모리를 사용합니다. 다차원 배열이기 때문에 10 개 이상의 객체가 있습니다. 동적 할당 방법 => typedef 배열 OneDimensionDownArrayT; – Alper

1

[] 연산자를 연속적으로 다차원 배열로 사용하려는 경우 각 []은 (덜 하나) 차원 배열을 반환해야합니다. 당신의 다차원 배열 유형 인 경우

는 :

template <class Type, int dim> MArray; 

는 그 다음 MArray<SomeType, n>::operator[]MArray<SomeType, n-1>을 반환해야합니다. 개체 (선호 참조)를 반환하는 특수한 1 차원 배열이나 기본 1 차원 배열을 반환하는 2 차원 배열을위한 특별한 경우가 있습니다. 이 예제는 지나치게 단순한 표기법을 사용했지만 핵심은 n-D [] 연산자가 (n-1) -D 배열을 반환한다는 것입니다.