指定模板函数中类成员的类型

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

Naw*_*waz 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!
};
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<>像我一样专门为传递给函数模板的每种类型.