2015-10-02 52 views
2

我正在寫一些函數模板使用犰狳線性代數庫,但它遇到一些錯誤。我仍然在學習C++及其方面,所以非常感謝任何可能的解決方案。我的大部分功能都像下面,函數模板在C++與Armadillo

template<typename T1> 
void some_function(const Mat<T1> & p) 
{ 
    unsigned int n = p.n_rows; 
    // do some stuffs... 
    // .... 
} 

我的主要功能包括:

Mat<double> A = ones<Mat<double>>(4,4); 
int a(2); 
some_function(A); // runs perfectly 
some_function(a*A); // compilation error as follows 

test_function.hpp:35:8: note: template argument deduction/substitution failed: 
test.cpp:22:17: note: ‘arma::enable_if2<true, const arma::eOp<arma::Mat<double>, arma::eop_scalar_times> >::result {aka const arma::eOp<arma::Mat<double>, arma::eop_scalar_times>}’ is not derived from ‘const arma::Mat<eT>’ 
some_function(a*A); 

如果我改變功能如下:

template<typename T1> 
void some_function(const T1 & p) 
{ 
    unsigned int n = p.n_rows; 
    // do some stuffs... 
    // .... 
} 

然後,它給人的編譯錯誤的如下:

test_function.hpp: In instantiation of ‘bool some_function(const T1&) [with T1 = arma::eOp<arma::Mat<double>, arma::eop_scalar_times>]’: 
test.cpp:22:17: required from here 
test_function.hpp:37:26: error: ‘const class arma::eOp<arma::Mat<double>, arma::eop_scalar_times>’ has no member named ‘n_rows’ 
unsigned int n = p.n_rows; 

但非模板功能完美工作,如

void some_function(const Mat<double> & p) 
{ 
    unsigned int n = p.n_rows(); 
    // do some stuffs... 
    // .... 
} 

任何解決方案?

+0

似乎'運算符*(double,Mat )'返回一個懶惰評估,而不是直接的'mat '...... – Jarod42

+0

錯誤是如此清楚。模板可以是'int'。 'int'是否有成員'n_rows()'? – manetsus

+0

@manetsus號''int'沒有'n_rows',但'Mat '有。在第二種情況下,因爲我只傳遞'Mat'類(或'int * Mat <>'...),我認爲只有該函數的版本纔會被實例化。 @ Jarod42是的,這可能是問題所在。 –

回答

1

我認爲,這些助手:

template <typename T> 
const Mat<T>& as_Mat(const Mat<T>& m) {return m;} 

template<typename T1, typename eop_type> 
Mat<typename T1::elem_type> as_Mat(const eOp<T1, eop_type>& X) 
{ 
    return {X}; 
} 

你可以寫:

template<typename T> 
void some_function(const T & p) 
{ 
    const auto& mat = as_mat(p); 
    unsigned int n = mat.n_rows(); 
    // do some stuffs... 
    // .... 
} 
+0

順便說一句,在第二種情況下使用初始化器列表是否有任何意義?快樂學習.. @ Jarod42 –

+0

我更喜歡在詳細的'Mat (X)'或者太隱式的'X'上寫'{X}'。 – Jarod42

3

使用.eval()成員函數的犰狳表達強行轉換成矩陣。

然後,您可以使用.eval()的結果作爲函數的輸入。例如:

mat A(10,20,fill::randu); 
mat B(10,20,fill::randu); 

some_function((A+B).eval()); 

另請注意,Mat類沒有名爲n_rows()的成員函數。相反,它有一個只讀變量,稱爲n_rows。例如:

unsigned int n = X.n_rows; 
+0

Ooops。 '()'只是一個愚蠢的錯字。感謝你的回答。 –

1

Jarod42的帖子,我把一些時間在這個問題上,發現了另一種可能的解決了這個問題,非常類似於Jarod42的一個。我回答這個問題是爲了解決像我這樣的問題。 我剛剛更改了第二個as_Mat功能,Jarod42已經寫好了。

template <typename T> 
const Mat<T>& as_Mat(const Mat<T>& m) {return m;} 


template<typename T> 
Mat<typename T::elem_type> as_Mat(const T& X) 
{ 
    return {X}; 
} 

並且所有用戶定義的函數都將像以前一樣包含一行。

template<typename T> 
void some_function(const T & X) 
{ 
    const auto& Y = as_Mat(X); 
    // do some stuffs with Y... 
    // .... 
} 

這樣,任何延遲評估將被轉換爲矩陣,例如, A+BA*Bi*Ai = INT,複雜<>,雙...)等等,等等等等

雖然我不知道代碼的性能,並且還作爲mtall提及.eval()函數,這個修正對於使用Armadillo構建模板化庫非常有幫助,其中庫用戶不需要每隔一段時間就放置.eval()。再次感謝大家的熱心幫助和關注。