C ++ Eigen Library:针对固定大小的矩阵进行转换

时间:2017-10-16 14:40:10

标签: c++ templates eigen

以下问题:

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)或通过Ref&lt; ..&gt;进行分配。 (参见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兼容的方法!

3 个答案:

答案 0 :(得分:3)

你可以根据条件的值使用C ++ 17中的constexpr if,如果值是U604 LRRC69 U586 PLEKHA5,C8orf77,ZNF252,LINGO2 U531 5S_rRNA,C3orf33 S784 CHST5,TMEM231,TM4SF20,TMEM184A ,则丢弃statement-false(如果存在),否则,statement-true被丢弃;然后代码不会导致编译错误。 e.g。

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 ...; 
}

答案 1 :(得分:1)

如果您使用的是C ++ 17,则可以编写

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

等。但是,您可以通过模板化generate_a_special_nxn_Matrix函数轻松实现C ++ 03兼容解决方案:

// 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 
}

答案 2 :(得分: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();
}