使用 C++ 时无法正确实例化模板功能库
我正在尝试创建一类固定大小的向量,主要用于几何目的, 其中向量长度不变:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的函数
util::times
具有签名:但在这一行中:
std::pointer_to_binary_function
的构造函数需要:您可以使用
const T& 修复该问题;
作为参数模板参数:请注意,我删除了
=
以在此处使用显式构造函数表示法。至少在(我的)GCC 中,赋值语法被编译器拒绝。由于您要创建一个执行乘法的二进制仿函数,而不是自定义
times
函数和仿函数包装器,因此您可以直接使用std::multiplies
来实现相同的效果:请注意在下一行中,
您将调用一个构造函数,该构造函数将
FixedVector
作为第一个参数,将一元函子作为第二个参数。这与您发布的构造函数代码不兼容:因为这个代码需要一个普通数组和一个函数指针。
Your function
util::times
has the signature:but in this line:
the constructor of
std::pointer_to_binary_function
is expecting:You can fix that by using
const T&
as argument template parameters: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 usestd::multiplies
to achieve the same:Note that in your next line,
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:since this one takes a plain array and a function pointer.
您无法从任何具有状态的函数对象转换为函数指针,即使如此,也只能将无状态的 C++0x lambda 转换为函数指针。您必须采用模板函数对象或多态对象,例如Boost、TR1和C++0x中的
函数
。此外,这非常晦涩难懂。为什么不直接进行常规乘法呢?它会比这种方法简单得多。
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.