使用 C++ 时无法正确实例化模板功能库

发布于 2024-11-27 19:45:29 字数 3937 浏览 1 评论 0原文

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

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::pointer_to_binary_function 被正确实例化为 std::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);
}

模板实例化参数中添加了一些const:

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

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

如果有一些额外的想法,我将非常感激。

I'm trying to create a class of fixed size vectors, to use mostly for geometrical purposes,
where vector length doesn't change:

template<typename T, int n>
class FixedVector
{
private:
    T m_rV[n]; // this is the only data member
     public:
              // class function members
              ...
}

This would have the advantage of compiler checking for operations with vectors of incompatible size.

I'm having problems when trying to build an operator* for this class (note: it is not a member). This operator should multiply the vector by a scalar, like this 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;
}

where times is the multiplication function of a scalar member of the vector

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

the code for the constructor in line 4 is

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

and pointer_to_binary_function and bind1st are STL functions from the header (Those who can help should know this already).

I'm getting the following compiler error in Visual Studio 2005 when calling

    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
    ]

It appears that
typename std::pointer_to_binary_function
is correctly instantiated to
std::pointer_to_binary_function
However, times still remains to its basic signature:
'T (__cdecl *)(const T &,const T &)


--- AFTER SOME EDITING ----------------------------------------------------------------

It was indicated to me that a function that my constructor requests a plain function as parameter: T (*)(const T &t1, const T &t2) and that STL functional objects won't be accepted.
The link here STL for_each served as a guide on how to do the corrections.

I started to changing from the util::copy function, called by constructor.

From:
template
void copy(T *dst, const T *src, size_t n, T (*f)(const T &))
{ for (; n>0; n--, dst++, src++)
{ *dst = f(*src);
} }

it became

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

Then, the constructor itself was templated. From:

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

it is now

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

Also added some consts to template instantiation parameters:

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

But I still get the same error (only that T has been replaced by const T; note that adding a & to indicate reference (const T&) will trigger an error and it seems that templates have problems with this, Boost and TR1 creating special solutions to deal with this - see Wikipedia TR1 reference wrapper).

The exact line of the error is this:

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

So I don't even reach the constructor.

I'd be very grateful with some extra ideas.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁月染过的梦 2024-12-04 19:45:29

您的函数 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 作为第一个参数,将一元函子作为第二个参数。这与您发布的构造函数代码不兼容:

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

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

Your function util::times has the signature:

T times(const T&, const T&)

but in this line:

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

the constructor of std::pointer_to_binary_function is expecting:

T times(T, T)

You can fix that by using const T& as argument template parameters:

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

Note that I removed the = to use explicit constructor notation here. At least in (my) GCC, the assignment syntax is rejected by the compiler.

Since you are creating a binary functor that does multiplication, instead of the custom times function and functor wrapper, you could directly use std::multiplies to achieve the same:

std::multiplies<T> op;

Note that in your next line,

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

you are calling a constructor that takes a FixedVector<T, n> as first argument, and a unary functor as second. This is not compatible with the constructor code you posted:

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

since this one takes a plain array and a function pointer.

酒中人 2024-12-04 19:45:29
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 转换为函数指针。您必须采用模板函数对象或多态对象,例如Boost、TR1和C++0x中的函数

此外,这非常晦涩难懂。为什么不直接进行常规乘法呢?它会比这种方法简单得多。

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

You cannot convert to a function pointer from any functional object with state, and even then, only stateless C++0x lambdas. You must take a template functional object, or a polymorphic one like function, found in Boost, TR1 and C++0x.

Besides, this is incredibly obscure. Why not just do a regular multiply? It would be far simpler than this approach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文