2012-06-19 136 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