C ++ - 专业化成员函数模板通过模板函子不编译 [英] C++ - specialising member function template via templated functor does not compile
问题描述
我想创建一个类,可以在浮点数和双精度数之间进行多态转换。也就是说,涉及的实例(由< 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屋!