C++部分模板实例化中的 typedef

C++ Typedef in Partial Template Instantiation

本文关键字:typedef 实例化 C++      更新时间:2023-10-16

我无法弄清楚为什么我的部分实例化模板没有在C++中编译。

我正在尝试提供一个类,该类根据传递给它的模板返回不同的类型:

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); }
};

但是,以下内容不会:

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 ab的类型特征匹配eVectorType_Matrix,出于某种原因,编译器说 ResultType 与 TypeOnea 的类型相同。我已经更改了工作专业化中的各种不同类型定义,但它们似乎都产生了相同的错误。

更具体地说,以下代码:

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. 在MatrixBase中,我认为

    static const int kNumCols = nRows;
    

    应该是

    static const int kNumCols = nCols;
    
  2. "a * b" 将返回

    MatrixBase<int, 2, 5>
    

    类型,而不是

    MatrixBase<float, 2, 5>
    

    需要添加复制构造函数来执行 int->float 转换。