2017-10-16 89 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