Can't correctly instantiate template when using C++ functional library
我试图创建一类固定大小的向量,主要用于几何目的,如果矢量长度不变:
1 2 3 4 5 6 7 8 9 | template<typename T, int n> class FixedVector { private: T m_rV[n]; // this is the only data member public: // class function members ... } |
这样做的好处是编译器可以检查带有不兼容大小向量的操作。
尝试为此类生成运算符*时遇到问题(注意:它不是成员)。该运算符应将向量乘以一个标量,如3*[1,2,3]=[3,6,9]。
1 2 3 4 5 6 | template<typename T, int n> FixedVector<T,n> operator*(const T &rX, const FixedVector<T,n> &cV) const { typename std::pointer_to_binary_function<T,T,T> op=(util::times<T>); FixedVector<T,n> cT(cV, std::bind1st(op, rX)); return cT; } |
其中,times是向量中标量成员的乘法函数
1 2 3 4 | template<typename T> inline T times(const T &t1, const T &t2) { return t1*t2; } |
第4行中的构造函数代码是
1 2 3 4 | template<typename T, int n> FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) { util::copy(m_rV, rV, n, f); } |
指针_to_binary_和bind1st是头中的stl函数(可以帮助的人应该已经知道这一点)。
调用时,Visual Studio 2005中出现以下编译器错误
1 | util::FixedVector<int,4> x; 3*x; |
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | fixed_vector.hpp(212) : error 2440: 'initializing' : cannot convert from 'T (__cdecl *)(const T &,const T &)' to 'std::pointer_to_binary_function<_Arg1,_Arg2,_Result>' with [ _Arg1=int, _Arg2=int, _Result=int ] No constructor could take the source type, or constructor overload resolution was ambiguous testproject.cpp(18) : see reference to function template instantiation 'util::FixedVector<T,n> util::operator *<T,4>(const T &,const util::FixedVector<T,n> &)' being compiled with [ T=int, n=4 ] |
看来typename std::指向二进制函数的指针已正确实例化为std::指向二进制函数的指针然而,时代仍然是其基本特征:'T(uu cdecl*)(const&;,const&;)
---编辑完成后-------------------------------------------------------------------我注意到,我的构造函数请求一个纯函数作为参数:t(*)(const&t;t1,const&t;t2),而stl函数对象将不会被接受。这里的链接stl for_每个都作为如何进行更正的指南。
我开始从由构造函数调用的util::copy函数进行更改。
来自:模板无效副本(t*dst,const t*src,size_tn,t(*f)(const&;)for(;n>0;n-,dst++,src++)*dst=f(*src);}
它变成了
1 2 3 4 5 | template<typename T, typename Function> void copy(T *dst, const T *src, size_t n, Function f) { for (; n>0; n--, dst++, src++) { *dst = (*f)(*src); } } |
然后,将构造函数本身模板化。来自:
1 2 3 4 | template<typename T, int n> FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) { util::copy(m_rV, rV, n, f); } |
现在是
1 2 3 4 5 | template<typename T, int n> template<class Function> FixedVector<T,n>::FixedVector(const FixedVector<T,n> &cV, Function f) { util::copy(m_rV, cV.m_rV, n, f); } |
还向模板实例化参数添加了一些常量:
1 2 3 4 5 6 | template<typename T, int n> FixedVector<T,n> operator*(const T &rX, const FixedVector<T,n> &cV) { typename std::pointer_to_binary_function<const T,const T,T> op(times<T>); FixedVector<T,n> cT(cV, std::bind1st(op, rX)); return cT; } |
但是我仍然会遇到同样的错误(只有t被const替换了。请注意,添加一个&;来表示引用(const&t;)会触发一个错误,而且模板似乎对此有问题,Boost和tr1创建特殊的解决方案来处理这个问题-请参阅维基百科tr1引用包装器)。
错误的确切行是:
1 | typename std::pointer_to_binary_function<const T,const T,T> op(times<T>); |
所以我连建造师都找不到。
我会非常感谢你提出了一些额外的想法。
您的函数
1 | T times(const T&, const T&) |
但在这一行中:
1 | typename std::pointer_to_binary_function<T,T,T> op=(util::times<T>); |
1 | T times(T, T) |
您可以使用
1 | typename std::pointer_to_binary_function<const T&, const T&, T> op(util::times<T>); |
注意,我删除了
由于您正在创建一个执行乘法的二进制函数,而不是自定义的
1 | std::multiplies<T> op; |
注意在下一行,
1 | FixedVector<T,n> cT(cV, std::bind1st(op, rX)); |
您正在调用一个以
1 2 3 4 | template<typename T, int n> FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) { util::copy(m_rV, rV, n, f); } |
因为这个函数接受一个普通数组和一个函数指针。
1 2 3 4 | template<typename T, int n> FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) { util::copy(m_rV, rV, n, f); } |
您不能从任何函数对象转换为函数指针,并且只有状态无状态的C++ +0x lambdas。您必须采取模板功能对象,或多态性的一个,如EDCOX1,0,在Boost,Tr1和C++0x中找到。
此外,这是令人难以置信的模糊。为什么不做一个正则乘法呢?这将比这种方法简单得多。