2012-06-08 2 views
1

행 및 열의 주요 저장소를 모두 지원할 수있는 Matrix 템플릿 클래스를 작성하고 있습니다. 이상적으로는 저장소 형식의 영향을받는 메서드 만 전문화하고 싶습니다. 그러나, 내가 (아래)와 같은 방법을 전문화하려고하면 아무것도 오류 메시지를 얻을.템플릿 클래스의 특수화 방법은 무엇입니까?

enum MatrixStorage 
{ 
    ColumnMajor, 
    RowMajor 
}; 

template< typename T, 
      unsigned rows, 
      unsigned columns, 
      MatrixStorage storage = ColumnMajor > 
class Matrix 
{ 
    public: 

    T & operator() (unsigned const & row, unsigned const & column); 

}; 

template< typename T, 
      unsigned rows, 
      unsigned columns > 
T & Matrix< T, rows, columns, ColumnMajor >:: 
operator() (unsigned const & row, unsigned const & column) 
{ 
    return elements[ (row + (rows * column)) % (rows * columns) ]; 
} 

template< typename T, 
      unsigned rows, 
      unsigned columns > 
T & Matrix< T, rows, columns, RowMajor >:: 
operator() (unsigned const & row, unsigned const & column) 
{ 
    return elements[ ((row * columns) + column) % (rows * columns) ]; 
} 

오류 출력 :

error C3860: template argument list following class template name must list parameters in the order used in template parameter list 
error C2976: 'maths::Matrix<T,rows,columns,storage>' : too few template arguments 
error C3860: template argument list following class template name must list parameters in the order used in template parameter list 

구문이 올바른 것 같습니다 다른 questions에 주어진 예에 따라. 그래도이 작업을 수행 할 수있는 유일한 방법은 클래스 자체를 전문화하는 것입니다 (아래 참조). 그러나 이는 저장소 형식에 종속되지 않는 모든 메서드를 복제하는 것을 의미합니다.

enum MatrixStorage 
{ 
    ColumnMajor, 
    RowMajor 
}; 

template< typename T, 
      unsigned rows, 
      unsigned columns, 
      MatrixStorage storage = ColumnMajor > 
class Matrix; 

template< typename T, 
      unsigned rows, 
      unsigned columns > 
class Matrix< T, rows, columns, ColumnMajor > 
{ 
    T & operator() (unsigned const & row, unsigned const & column); 
}; 

template< typename T, 
      unsigned rows, 
      unsigned columns > 
class Matrix< T, rows, columns, RowMajor > 
{ 
    T & operator() (unsigned const & row, unsigned const & column); 
}; 
+1

, 나는 한 번 작업을 템플리트하려고 40시간 정도를 소비 할 수있다 행렬 클래스에서. 내 마음 속에서 왼쪽 곱셈과 오른쪽 곱셈은 매우 유사하여 코드를 복제하는 것은 의미가 없었습니다. 생각해 보면 행/열 대다수 질문과 다소 유사합니다. 내가 발견 한 것처럼 보인 것은 C++의 뛰어난 템플릿 기능이 이런 종류의 사용을 염두에두고 설계되지 않았다는 것입니다. 그것은 잘 작동하지 않았다. 결국, 나는이 목적을 위해 템플릿 사용을 포기하고 중단했습니다. 네가 운이 좋기를 바랍니다. – thb

+0

40 시간 전에는 템플릿이 이런 식으로 사용되는 라이브러리를 보았지만 나는 당신과 의견이 다를 수 있습니다. 주요 매력은 메모리/런타임 오버 헤드를 줄인다는 것입니다. David는 기능을 위임하는 데 몇 가지 도우미 클래스가 주어진다면 가능할 것이라고 제안했습니다. – PeddleSpam

답변

3

템플릿의 멤버 함수를 포함하는 함수 템플릿을 부분적으로 특수화 할 수 없습니다. 대신 필요한 기능을 제공하는 템플릿 도우미 클래스를 만든 다음 템플릿의 멤버 함수에서 클래스 템플릿으로 호출을 전달할 수도 있습니다.

또는 유스 케이스가 매우 간단하므로 좌표와 좌표가 지정된 배열의 색인을 제공하는 도우미 함수 (템플릿 또는 그렇지 않은 경우 풀 클래스 일 필요는 없음)를 작성할 수 있습니다. 방법.

template <MatrixStorage m> 
int index_of(int row, int col, int rows, int columns) { 
    return (row + (rows * column)) % (rows * columns); 
} 
template <> 
int index_of<RowMajor>(int row, int col, int rows, int columns) { 
    return ((row * columns) + column) % (rows * columns); 
} 

당신은 관심사 경우는 런타임에 확인됩니다 유형 MatrixStorage의 추가 매개 변수를 취함으로써 비 템플릿 (단순 if)

+0

나는 이전 시도와 비슷한 것을했다. 위의 함수 연산자 예제에서는 작동하지만 할당 연산자 및 복사 생성자와 같은 다른 메서드에서는 작동하지 않습니다. 이러한 메서드에서는 저장소 형식에 따라 배열을 다르게 반복합니다. 다른 도우미 클래스를 만들고 배열에 대한 포인터를 전달할 수는 있지만 조금 복잡해 보입니다./ – PeddleSpam

+0

대부분의 경우 상속은이 (부분 특수화)에 대해 정확하게 남용됩니다. 공통 코드를 기본 클래스로 이동 한 다음이 클래스에서 파생하고 특수화를 수행 할 수 있습니다. 또한 할당의 경우'[0, rows * cols]'범위의 단일 루프를 사용하여 행렬이 행 주열인지 행렬인지를 무시할 수 있습니다. –

+0

@ DavidRodríguez-dribeas : Yours 좋은 해결책이고 나는 그것을 좋아한다 (그리고 그것을 upvoted했다). 그러나, 나는 OP가 미묘한 문제가 있다고 생각한다. 나는 그가 한 번에 전체 행이나 열을 자신의 행렬 객체에 액세스해야한다고 생각합니다. 그렇다면 개별 요소를 가져 오는 것이 너무 느릴 수 있습니다. – thb

관련 문제