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

Can't correctly instantiate template when using C++ functional library

本文关键字:实例化 C++ 函数      更新时间:2023-10-16

我正在尝试创建一类固定大小的向量,主要用于几何目的,其中向量长度不变:

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]。

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 是向量的标量成员的乘法函数

template<typename T>
inline T times(const T &t1, const T &t2)
{   return t1*t2;
}

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

pointer_to_binary_function和 bind1st 是标头中的 STL 函数(那些可以提供帮助的人应该已经知道这一点(。

调用时,我在 Visual Studio 2005 中收到以下编译器错误

    util::FixedVector<int,4> x; 3*x;

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
    ]

看来 类型名称 std::p ointer_to_binary_function被正确实例化为 std::p ointer_to_binary_function然而,时代仍然停留在它的基本特征上: 'T (__cdecl *((const T &,const T &(


经过一些编辑----------------------------------------------------------------后---

有人向我指出,我的构造函数请求一个普通函数作为参数:T(*((const T &t1,const T &t2(,并且STL函数对象将不被接受。STL for_each此处的链接可作为如何进行更正的指南。

我开始从构造函数调用的util::copy函数进行更改。

从: 模板 void copy(T *dst, const T *src, size_t n, T (*f((const T &(( { for (; n>0; n--, dst++, src++( { *dst = f(*src(; } }

它变成了

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

然后,构造函数本身被模板化。从:

template<typename T, int n>
FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) 
{   util::copy(m_rV, rV, n, f);
}

就是现在

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

还在模板实例化参数中添加了一些常量:

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 T 替换;请注意,添加 & 以指示引用 (const T&( 将触发错误,似乎模板对此有问题,Boost 和 TR1 创建特殊解决方案来处理这个问题 - 请参阅维基百科 TR1 引用包装器(。

错误的确切行是这样的:

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

所以我什至没有到达构造函数。

如果能提供一些额外的想法,我将不胜感激。

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

T times(const T&, const T&)

但在这一行中:

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

std::pointer_to_binary_function 的构造函数期望:

T times(T, T)

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

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

请注意,我删除了在此处使用显式构造函数表示法=。 至少在(我的(GCC中,赋值语法被编译器拒绝。

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

std::multiplies<T> op;

请注意,在下一行中,

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

您正在调用一个构造函数,该构造函数将 FixedVector<T, n> 作为第一个参数,将一元函子作为第二个参数。 这与你发布的构造函数代码不兼容:

template<typename T, int n>
FixedVector<T,n>::FixedVector(const T rV[n], T (*f)(const T &)) 
{   util::copy(m_rV, rV, n, f);
}

因为这个需要一个普通数组和一个函数指针。

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 lambda。您必须采用模板函数对象,或多态对象,如 function ,在 Boost、TR1 和 C++0x 中找到。

此外,这非常晦涩难懂。为什么不做一个常规的乘法呢?它比这种方法简单得多。