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

时间:2011-05-31 09:09:31

标签: 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);
}

但是我想避免一直强制返回类型为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; }

4 个答案:

答案 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。