我有这个模板功能:
template <class P>
double Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
但是我想避免一直强制返回类型为double
- P :: x和P :: y也可以是ints,我在这两种情况下都需要这个函数。有没有办法指定x和y的类型,像这样?
//doesn't compile; can't deduce template argument for T
template <typename T, class P>
T Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
编辑:我的编译器是VC2005
编辑2:遗憾地忘记提及:遗憾的是我无法修改P的结构的实现;我处理的一种点类型是MFC / ATL的CPoint,其硬编码为{ long x; long y; }
。
答案 0 :(得分:7)
编译器不能从函数参数中推导出函数模板的返回类型。类型推导仅使用函数参数完成。
在C ++ 03中,您可以在类中定义 typedef :
struct A //suppose A is going to be type argument to your function template
{
int x, y; //I'm assuming type of x and y is same!
typedef int value_type; //type of x and y!
};
然后你要重新编写你的函数:
template <class P>
typename P::value_type Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
注意现在的返回类型,它是一个依赖类型。它的:
typename P::value_type
此处需要关键字typename
。
好吧,正如你所说,你不能修改你的结构,那么你可以改用你的特征。以下是如何做到这一点:
template<typename T> struct PTraits;
//Suppose this is your type which you can't modify
struct A //A is going to be type argument to your function template
{
long x, y;
};
//specialization: defining traits for struct A
template<>
struct PTraits<A>
{
typedef long value_type; //since type of A::x and A::y is long!
};
您的功能模板如下所示:
template <class P>
typename PTraits<P>::value_type Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
注意返回类型;它现在略有不同:
typename PTraits<P>::value_type
同样,value_type
是一个从属名称,因此需要关键字typename
。
请注意,您必须为传递给函数模板的每种类型专门化PTraits<>
,就像我一样。
答案 1 :(得分:3)
我喜欢使用特征风格方法:
template<typename T> struct DeterminantReturnInfo {};
template<> struct DeterminantReturnInfo<MyType> { typedef MyOtherType ReturnType; }
template< typename T >
typename DeterminantReturnInfo<T>::ReturnType Determinant( const P & a, const P & B, const P & c)
{
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
如果您希望默认为加倍,则只需将typedef double ReturnType;
添加到初始模板。
答案 2 :(得分:2)
如果您使用的是Visual Studio 2010或GCC 4.5+,则可以使用尾随返回类型表单:
template<class P>
auto fun(const P& a) -> decltype(a.x + a.y){
return a.x + a.y;
}
感谢decltype
我们自动获得正确的返回类型。此外,计算仍然只在正文中进行一次,而不是在尾随回报中进行。
答案 3 :(得分:0)
检查您的返回键入类型成员变量x / y的类型。您可能不会返回,所以输入T。