C ++ - 专业化成员函数模板通过模板函子不编译 [英] C++ - specialising member function template via templated functor does not compile

查看:201
本文介绍了C ++ - 专业化成员函数模板通过模板函子不编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I wish to create a class that can convert between arrays of floats and doubles polymorphically. That is, the instance concerned (parameterised by <double> or <float>) and the decision to pass a float* or double* is decided at runtime, not statically.

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

As a proposed answer to another question, but modified according to this answer (because I understand it's not possible to fully specialise a member function template inside a class), a pure virtual base class BaseDest that provides simple overloaded member functions is sub-classed to define DestImpl<T>. I use this base class to maintain a dynamic collection of DestImpl<T> instances, with varying T. This class provides explicit overloads of the assign() member function; one for a double *, and another for a float *. The idea is that at run-time, BaseDest::assign() is called via a polymorphic pointer or reference, and this in turn calls the correct virtual assign() member function in DestImpl<T>.

现在,是非常重要的,那么数组的非指针类型匹配 DestImpl 中的T, fast_copy()函数被调用(也许是memcpy),并且当类型不匹配时,执行较慢的逐个项目拷贝。因此, assign()成员函数将其卸载到模板化的函子。对于该函子有两个特殊化 - 其中函子的类型参数匹配 DestImpl< T> 的类型(因此调用快速拷贝)回到一个捕获所有其他情况(并调用慢拷贝)。

Now, it is important that then the non-pointer type of the array matches T in DestImpl<T>, that a fast_copy() function is called (perhaps a memcpy), and when the types do not match a slower statically-cast-item-by-item copy is performed. So the assign() member function offloads this to a templated functor. There are two specialisations for this functor - one where the type parameter of the functor matches the type of DestImpl<T> (and therefore invokes a fast copy), and a fall-back one that catches all other cases (and invokes a slow copy).

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

However, I am unable to get the following code to compile. The comments show where the compiler error and warning appear - I suspect they are related. What I don't understand is why the second specialisation of apply_helper is unable to be instantiated as 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
}

编辑:似乎工作 - 将 DestImpl< T> 类定义中的 assign_helper 结构我不知道这是正确的方法,但它似乎工作到目前为止:

here's something that does seem to work - moving the assign_helper struct (now a class) out of the DestImpl<T> class definition. I'm not sure this is the right way to do it, but it does seem to work so far:

// 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<类型名称U> 模板<>

The above is the cause of your error. The warning explicitly tells you that this definition will never be used. What you want instead of template < typename U > is template <>.

这篇关于C ++ - 专业化成员函数模板通过模板函子不编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆