2012-06-19 232 views
6

信息:返回类型模板函数

我正在努力学习模板元编程(按照this book)。他们给出的一个有用的例子是尺寸分析。我在书中执行它,一切都很好; see here

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

我有拥有所有必要的操作与乘法/纯量划分等3 Vector类,所以我想这样做

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说明符的地方?要么;是否有可能这样做,如果不是如何计算函数的返回类型?

谢谢。

回答

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>

+0

是的,我可以告诉编译器输出,我得到了整个函数签名。我不知道为什么我这么复杂,你的例子编译得很好:)默认构造函数的要求对我来说不是问题。 – Dan

+2

@Dan:请注意,本书是在C++ 11和'decltype' /'auto'可用性之前编写的,这使得**变得更加复杂。 –

+2

用'decltype(std :: declval ()* std :: declval ())'替换'decltype(T1()* T2())',而且不再需要默认的可构造性。 – ildjarn