2017-10-16 127 views
1

以下問題:C++庫的本徵:投給固定大小的矩陣

template<int nDim> 
void foo (){ 

    Eigen::Matrix<double, nDim, nDim> bar; 

    if (nDim == 3){ 
     bar = generate_a_special_3x3_Matrix();} 
    else if (nDim == 2){ 
     bar = generate_a_special_2x2_Matrix();} 


// ... further math here 
} 

等等,當然由於靜態斷言,此代碼不能編譯。然而,它確保在運行時從不發生問題。

目前知道的解決方案是通過.block(3,3)或通過參考< ..>(參見Cast dynamic matrix to fixed matrix in Eigen)的作業。

.block方法:

template<int nDim> 
void foo (){ 

    Eigen::Matrix<double, nDim, nDim> bar; 

    if (nDim == 3){ 
     bar.block(3,3) = generate_a_special_3x3_Matrix();} 
    else if (nDim == 2){ 
     bar.block(2,2) = generate_a_special_2x2_Matrix();} 


// ... further math here 
} 

然而,這兩種方法都涉及了正確的矩陣大小,這是不是真的有必要運行時檢查,並編寫的代碼是不是真的很美。

我並不在乎運行時開銷(儘管避免它會很好),但是我的眼中寫的代碼並不是很乾淨,因爲.block()的意圖不會立即清除其他人。 有沒有更好的方法,例如像一個演員?

編輯:兩個很好的解決方案發布(如果constexpr),但是,我需要一個C++ 11/14兼容的方法!

回答

1

能夠完美地與C++ 98棒,你可以濫用comma initializer語法:

template<int N> 
void foo(){ 
    Eigen::Matrix<double, N, N> bar; 
    if(N==3)  bar << Matrix3d(); 
    else if(N==2) bar << Matrix2d(); 
} 
+0

本案例中的完美解決方案!謝謝! – macmallow

3

根據條件的值,您可以使用C++ 17中的constexpr if,如果值爲true,則丟棄statement-false(如果存在),否則將丟棄statement-true;那麼代碼不會導致編譯錯誤。例如

template<int nDim> 
void foo() { 

    Eigen::Matrix<double, nDim, nDim> bar; 

    if constexpr (nDim == 3) { 
     bar = generate_a_special_3x3_Matrix(); 
    } else constexpr if (nDim == 2) { 
     bar = generate_a_special_2x2_Matrix(); 
    } 

    // ... further math here 
} 

或使generate_a_special_Matrix功能模板,例如,

template <int nDim> 
Eigen::Matrix<double, nDim, nDim> generate_a_special_Matrix(); 

template <> 
Eigen::Matrix<double, 2, 2> generate_a_special_Matrix<2>() { 
    ... generating ... 
    return ...; 
} 

template <> 
Eigen::Matrix<double, 3, 3> generate_a_special_Matrix<3>() { 
    ... generating ... 
    return ...; 
} 

然後

template<int nDim> 
void foo() { 

    Eigen::Matrix<double, nDim, nDim> bar; 
    bar = generate_a_special_Matrix<nDim>(); 

    // ... further math here 
} 
+0

好吧,你用一分鐘打我(爲模板解決方案) – chtz

+0

尼斯解決方案,謝謝你;但是,我會喜歡堅持GCC 4.8? – macmallow

+0

@macmallow第二種解決方案的問題是什麼? – songyuanyao

1

如果您正在使用C++ 17,你可以寫

if constexpr (nDim == 3){ bar = generate_a_special_3x3_Matrix();} 

等,但你可以很容易地通過templatizing實現C++ 03兼容的解決方案您的generate_a_special_nxn_Matrix功能:

// general declaration (without implementation): 
template<int nDim> 
Eigen::Matrix<double, nDim, nDim> generate_a_special_nxn_Matrix(); 
template<> 
Eigen::Matrix<double, 2, 2> generate_a_special_nxn_Matrix(){ 
    return generate_a_special_2x2_Matrix(); 
} 
template<> 
Eigen::Matrix<double, 3, 3> generate_a_special_nxn_Matrix(){ 
    return generate_a_special_3x3_Matrix(); 
} 

然後直接調用

template<int nDim> 
void foo (){ 

    Eigen::Matrix<double, nDim, nDim> bar = generate_a_special_nxn_Matrix<nDim>(); 

    // ... further math here 
} 
+0

謝謝,您的C++ 03可以,但是,它隱藏了實際的操作,因此在目前的情況下並不適合。 C++ 17的方法很好,但我需要堅持GCC 4.8。 – macmallow