【问题标题】:C++ - specialising member function template via templated functor does not compileC++ - 通过模板仿函数专门化成员函数模板不编译
【发布时间】:2013-03-26 22:33:40
【问题描述】:

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

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

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

但是,我无法编译以下代码。 cmets 显示编译器错误和警告出现的位置 - 我怀疑它们是相关的。我不明白的是为什么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&lt;T&gt; 类定义中移出。我不确定这是不是正确的方法,但到目前为止它似乎确实有效:

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

【问题讨论】:

    标签: c++ templates type-conversion template-specialization


    【解决方案1】:
    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 &lt; typename U &gt;,而是template &lt;&gt;

    【讨论】:

    • 谢谢,但这是最初的问题 - 使用 template &lt;&gt; 会导致错误“在类范围内显式专门化 'assign_helper'”,这显然是非法的。我在问题中所做的 EDIT 将此参数化仿函数定义移到了类定义之外,这似乎使事情变得清晰,尽管我必须相应地更改模板参数化。
    • 啊,对不起。我们今天都学到了一些东西。有关该主题的更多信息:stackoverflow.com/questions/6301966/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    相关资源
    最近更新 更多