使用C ++函数库时无法正确实例化模板

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

所以我连建造师都找不到。

我会非常感谢你提出了一些额外的想法。


您的函数util::times具有以下签名:

1
T times(const T&, const T&)

但在这一行中:

1
typename std::pointer_to_binary_function<T,T,T> op=(util::times<T>);

std::pointer_to_binary_function的建设者期望:

1
T times(T, T)

您可以使用const T&作为参数模板参数来解决这个问题:

1
typename std::pointer_to_binary_function<const T&, const T&, T> op(util::times<T>);

注意,我删除了=以在这里使用显式构造函数表示法。至少在(my)gcc中,编译器拒绝了赋值语法。

由于您正在创建一个执行乘法的二进制函数,而不是自定义的times函数和函数包装器,因此可以直接使用std::multiplies来实现相同的功能:

1
std::multiplies<T> op;

注意在下一行,

1
FixedVector<T,n> cT(cV, std::bind1st(op, rX));

您正在调用一个以FixedVector作为第一个参数,以一元函数作为第二个参数的构造函数。这与您发布的构造函数代码不兼容:

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中找到。

此外,这是令人难以置信的模糊。为什么不做一个正则乘法呢?这将比这种方法简单得多。