返回模板函数的类型

时间:2012-06-19 09:07:29

标签: c++ templates c++11 decltype

的信息:

我目前正在尝试学习模板元编程(通过以下this book)。他们给出的一个有用的例子是尺寸分析。我在书中实现了它,一切都很好; see here

然而,我的问题是,我想使用混合类型的维度分析框架。通过这个我的意思是你可以说一个标量的质量乘以一个矢量与加速度的维度,以给出一个矢量力。由于它位于链接中,因此它们仅对所有操作的输入和输出使用相同类型T

我有一个3向量类,它有所有必要的操作,用于乘以/除以标量等,所以我想做类似的事情

quantity<double,mass> m(1.0);
quantity<vect,acceleration> a(vect(0.0,0.0,-9.81));
quantity<vect,force> f = m*a;

首次尝试:

为了实现这一点,我尝试将书中的示例用于处理两种不同类型作为operator*operator/的输入,但是当涉及到返回类型时,我遇到了问题。

我知道double * vect的返回类型是vect,但如果它们是vect * double的另一种方式,它仍然是vect。更差;原则上,返回类型可以是任何东西。所以我想要一种方法将operator*扩展到像

这样的东西
template<class T1, class T2, class Dim1, class Dim2>
quantity<X, typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type>
operator*(const quantity<T1,Dim1>& q1, const quantity<T2,Dim2>& q2)
{
    return quantity<X,
                    typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type>
                   (q1.value()*q2.value());
}

其中Xq1.value()*q2.value()的返回类型,在编译时推断出来。我尝试将另一个模板类T3添加到签名并让它返回T3,但似乎无法推断出T3应该是什么。

第二次尝试:

接下来我尝试使用decltype,如下所示

template<class T1, class T2>
struct return_type
{
    auto mult_f(const T1& a, const T2& b)->decltype(a*b){return a*b;}
    typedef decltype(mult_f) type;
};

template<class T1, class T2, class Dim1, class Dim2>
quantity<typename return_type<T1,T2>::type, typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type>
operator*(const quantity<T1,Dim1>& q1, const quantity<T2,Dim2>& q2)
{
    return quantity<typename return_type<T1,T2>::type,
                    typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type>
                   (q1.value()*q2.value());
}

然而,这会引发许多难以理解的编译器错误。

问题:

我的问题是,我是否以正确的方式使用decltype,但遗漏了一些语法,例如某个typename说明符?要么;甚至可以这样做,如果不是,怎么可能计算函数的返回类型?

感谢。

1 个答案:

答案 0 :(得分:6)

好的,首先类型return_type<T1,T2>::type不是您所期望的类型,而是方法的类型,即T3 (return_type::*)(const T1&, const T2&)T3是您期望的类型。如果要使用中间类,可以使用:

template <typename T1, typename T2>
struct return_type
{
  typedef decltype(std::declval<T1>()*std::declval<T2>()) type;
};

但您也可以直接使用decltype(T1()*T2())来获取产品的类型。

编辑:我使用ildjarn的建议编辑了代码,因此不需要默认构造类型。只是不要忘记包含<utility>