2014-02-20 6 views
1

У меня возникли проблемы с выяснением того, почему мой частично созданный шаблон не компилируется на C++.C++ Typedef в частичном создании шаблона

Я пытаюсь представить класс, который возвращает различные типы на основе шаблонов, которые передаются ему:

enum EVectorType { 
    eVectorType_Scalar, 
    eVectorType_Vector, 
    eVectorType_Matrix 
}; 

template< 
    EVectorType kVectorTypeOne, 
    EVectorType kVectorTypeTwo, 
    typename TypeOne, 
    typename TypeTwo> 
class MultSwitch { 
private: 
    const TypeOne &m_A; 
    const TypeTwo &m_B; 
public: 
    typedef TypeOne ResultType; 
    MultSwitch(const TypeOne &a, const TypeTwo &b) 
    : m_A(a), m_B(b) { } 

    ResultType GetMultiplication() const { return m_A * m_B; } 
}; 

Класс используется как перегрузка на * оператора:

template<typename T> 
class VectorTraits { 
    public: 
    static const EVectorType kVectorType = eVectorType_Scalar; 
}; 

template<typename T, const int N> 
class VectorTraits<VectorBase<T, N> > { 
public: 
    static const EVectorType kVectorType = eVectorType_Vector; 
}; 

template<typename TypeOne, typename TypeTwo> 
static inline 
    typename MultSwitch< 
    VectorTraits<TypeOne>::kVectorType, 
    VectorTraits<TypeTwo>::kVectorType, 
    TypeOne, TypeTwo 
    >::ResultType 
operator*(const TypeOne &v1, const TypeTwo &v2) { 
    typedef MultSwitch< 
    VectorTraits<TypeOne>::kVectorType, 
    VectorTraits<TypeTwo>::kVectorType, 
    TypeOne, TypeTwo 
    > VSwitch; 
    return VSwitch(v1, v2).GetMultiplication(); 
} 

следующие специализации работы по назначению:

template<typename TypeOne, typename TypeTwo> 
class MultSwitch< 
    eVectorType_Scalar, 
    eVectorType_Vector, 
    TypeOne, TypeTwo> { 
private: 
    const TypeOne &m_A; 
    const TypeTwo &m_B; 

public: 
    typedef TypeTwo ResultType; 

    MultSwitch(const TypeOne &a, const TypeTwo &b) 
    : m_A(a), m_B(b) { } 

    ResultType GetMultiplication() const { return ScalarMultiply(m_B, m_A); } 
}; 

template<typename TypeOne, typename TypeTwo> 
class MultSwitch< 
    eVectorType_Vector, 
    eVectorType_Scalar, 
    TypeOne, TypeTwo> { 
private: 
    const TypeOne &m_A; 
    const TypeTwo &m_B; 

public: 
    typedef TypeOne ResultType; 

    MultSwitch(const TypeOne &a, const TypeTwo &b) 
    : m_A(a), m_B(b) { } 

    ResultType GetMultiplication() const { return ScalarMultiply(m_A, m_B); } 
}; 

template<typename TypeOne, typename TypeTwo> 
class MultSwitch< 
    eVectorType_Vector, 
    eVectorType_Vector, 
    TypeOne, TypeTwo> { 
private: 
    const TypeOne &m_A; 
    const TypeTwo &m_B; 

public: 
    typedef typename TypeOne::ScalarType ResultType; 

    MultSwitch(const TypeOne &a, const TypeTwo &b) 
    : m_A(a), m_B(b) { } 

    ResultType GetMultiplication() const { return m_A.Dot(m_B); } 
}; 

Ho Веверу, следующий не будет:

template<typename TypeOne, typename TypeTwo> 
class MultSwitch< 
    eVectorType_Matrix, 
    eVectorType_Matrix, 
    TypeOne, TypeTwo> { 
private: 
    const TypeOne &m_A; 
    const TypeTwo &m_B; 

public: 
    typedef MatrixBase<typename TypeOne::ScalarType, TypeOne::kNumRows, TypeTwo::kNumCols> ResultType; 

    MultSwitch(const TypeOne &a, const TypeTwo &b) 
    : m_A(a), m_B(b) { } 

    ResultType GetMultiplication() const { return m_A.MultiplyMatrix(m_B); } 
}; 

Всякий раз, когда я пишу выражение a * b где черты типовым a и b матча eVectorType_Matrix, по некоторым причинам, компилятор говорит, что ResultType того же типа, как TypeOne или a. Я изменил различные типы typedefs в рабочих специализациях, но все они, похоже, вызывают такую ​​же ошибку.

Более конкретно, следующий код:

template <typename T, const int nRows, const int nCols> 
class MatrixBase { 
public: 
    typedef T ScalarType; 
    static const int kNumRows = nRows; 
    static const int kNumCols = nRows; 
    ... 
}; 

template<typename T, const int N, const int M> 
class VectorTraits<MatrixBase<T, N, M> > { 
public: 
    static const EVectorType kVectorType = eVectorType_Matrix; 
}; 

MatrixBase<int, 2, 3> a; 
... 

MatrixBase<int, 3, 5> b; 
... 

MatrixBase<float, 2, 5> amb = a * b; 

Выдает следующую ошибку:

TestMatrix.cpp:145:42: error: conversion from ‘MultSwitch<(EVectorType)2u, (EVectorType)2u, MatrixBase<int, 2, 3>, MatrixBase<int, 3, 5> >::ResultType {aka MatrixBase<int, 2, 3>}’ to non-scalar type ‘MatrixBase<float, 2, 5>’ requested 
    MatrixBase<float, 2, 5> amb = a * b; 
+1

Я считаю, что у вас есть две проблемы: (1) В MatrixBase, я думаю, "статический Const ИНТ kNumCols = NROWS;" должен быть «static const int kNumCols = nCols;» (2) «a * b» вернет MatrixBase , а не MatrixBase . Вам нужно будет добавить конструктор копирования для выполнения преобразования int-> float. – Glenn

+0

Да, я только что поймал. Добавьте его в качестве ответа! У меня уже есть конструктор копирования. :) – Mokosha

ответ

3

Я считаю, у вас есть две проблемы:

  1. В MatrixBase, я думаю

    static const int kNumCols = nRows; 
    

    должен быть

    static const int kNumCols = nCols; 
    
  2. "а * б" будет возвращать тип

    MatrixBase<int, 2, 5> 
    

    , не

    MatrixBase<float, 2, 5> 
    

    Вам нужно добавить конструктор копирования для выполнения преобразование int-> float.

+0

Это было # 1. Благодаря! – Mokosha