mar*_*han 1 c++ templates traits
我有这个模板功能:
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);
}
Run Code Online (Sandbox Code Playgroud)
但是我想避免一直强制返回类型double--P :: x和P :: y也可以是int,我在两种情况下都需要这个函数.有没有办法指定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);
}
Run Code Online (Sandbox Code Playgroud)
编辑:我的编译器是VC2005
edit2:遗憾地忘记提及:遗憾的是我不能修改P的结构的实现; 我处理的一种点类型是MFC/ATL的CPoint,它们被硬编码为{ long x; long y; }.
编译器不能从函数参数中推导出函数模板的返回类型.类型推导仅使用函数参数完成.
在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!
};
Run Code Online (Sandbox Code Playgroud)
然后你要重新编写你的函数:
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);
}
Run Code Online (Sandbox Code Playgroud)
现在注意return类型,它是一个依赖类型.它的 :
typename P::value_type
Run Code Online (Sandbox Code Playgroud)
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!
};
Run Code Online (Sandbox Code Playgroud)
你的功能模板看起来像这样:
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);
}
Run Code Online (Sandbox Code Playgroud)
注意返回类型; 现在略有不同:
typename PTraits<P>::value_type
Run Code Online (Sandbox Code Playgroud)
同样,value_type是一个从属名称,因此关键字typename是必需的.
请注意,您必须PTraits<>像我一样专门为传递给函数模板的每种类型.