通过模板化的函函数特化成员函数模板无法编译

C++ - specialising member function template via templated functor does not compile

本文关键字:函数模板 成员 编译 函数      更新时间:2023-10-16

我希望创建一个类,可以在浮点数和双精度数组之间进行多态转换。也就是说,相关的实例(由<double><float>参数化)和传递float*double*的决定是在运行时决定的,而不是静态的。

作为对另一个问题的建议答案,但根据这个答案进行修改(因为我理解在类内部完全专门化成员函数模板是不可能的),提供简单重载成员函数的纯虚拟基类BaseDest被子类化为定义DestImpl<T>。我使用这个基类来维护DestImpl<T>实例的动态集合,其中T是不同的。该类提供assign()成员函数的显式重载;一个用于double *,另一个用于float *。其思想是,在运行时,BaseDest::assign()通过多态指针或引用调用,这反过来调用DestImpl<T>中正确的虚拟assign()成员函数。

现在,重要的是数组的非指针类型匹配DestImpl<T>中的T,调用fast_copy()函数(可能是memcpy),当类型不匹配时,执行较慢的逐项静态强制转换复制。因此assign()成员函数将其卸载到模板化的函子。这个函子有两种特化——一种是函子的类型参数匹配DestImpl<T>的类型(因此调用快速复制),另一种是捕获所有其他情况(并调用慢速复制)的回退。

但是,我无法编译以下代码。注释显示了编译器错误和警告出现的位置——我怀疑它们是相关的。我不明白的是为什么apply_helper的第二个专门化不能被实例化为apply_helper<double>

class BaseDest {
public:
  virtual ~BaseDest() {}
  virtual void assign(const double * v, size_t cnt) = 0;
  virtual void assign(const float * v, size_t cnt) = 0;
};
template <typename T>
class DestImpl : public BaseDest {
public:
  void assign(const double * v, size_t cnt) {
    assign_helper<T>()(v, cnt);
  }
  void assign(const float * v, size_t cnt) {
    assign_helper<T>()(v, cnt);  // ERROR: no matching function for call to object of type 'assign_helper<double>'
  }   
protected:
  template <typename U>
  struct assign_helper {
    void operator()(const U * v, size_t cnt) {
      for (size_t i = 0; i < cnt; ++i) {
        //slow_copy(v[i]);
      }
    }
  };
  template <typename U>
  struct assign_helper<T> {  // WARNING: Class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used
    void operator()(const T * v, size_t cnt) {
      //fast_copy(v, cnt);
    }
  };
};
void test() {
  DestImpl<double> d;  // error mentioned above appears when this is present
}

编辑:这里的东西似乎确实工作-移动assign_helper结构(现在是一个类)的DestImpl<T>类定义。我不确定这是正确的方法,但到目前为止,它似乎确实有效:

// slow copy between different types
template <typename T, typename U>
class assign_helper {
public:
  void operator()(const U *v, size_t cnt) {
    // slow copy
  }
};
// fast copy between same types
template <typename T>
class assign_helper<T, T> {
public:
  void operator()(const T * v, size_t cnt) {
    // fast copy
  }
};

class BaseDest {
public:
  virtual ~BaseDest() {}
  virtual void assign(const double * v, size_t cnt) = 0;
  virtual void assign(const float * v, size_t cnt) = 0;
};
template <typename T>
class DestImpl : public BaseDest {
public:
  virtual void assign(const double * v, size_t cnt) {
    assign_helper<T, double>()(v, cnt);
  }
  virtual void assign(const float * v, size_t cnt) {
    assign_helper<T, float>()(v, cnt);
  }
};
template <typename U>
  struct assign_helper<T> {  // WARNING: Class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used
以上就是造成你错误的原因。警告显式地告诉您永远不会使用此定义。你想要的template < typename U >template <>