特征库:模板中的断言失败

时间:2017-06-05 18:47:04

标签: c++ eigen assertions

我有一个模板化函数,它应该生成一个编译时已知的固定大小的Vector,它取决于模板参数:

template <int nSize> 
Eigen::Matrix<double, nSize, 1> myFunc()
{
    switch(nSize){
    case 2: return ExternalLibrary::generate_Vector_2d();
    case 3: return ExternalLibrary::generate_Vector_3d();
    }
}

然而,当我编译这段代码时,我得到一个失败的断言,因为Vector_2d大小不符合3d大小:

Eigen::Vector3d testVector3d = myFunc<3>(); // failed, because 3d doesn't fit the theoreticelly possible 2d 

基本上,失败的断言是可以理解的,但当然这在运行时永远不会成为问题。我怎样才能绕过这个失败的断言?或者是否有比切换条件更优雅的方式?

谢谢!

1 个答案:

答案 0 :(得分:3)

只需声明模板函数并且不定义它,然后定义两个特化:

template <int nSize>
Eigen::Matrix<double, nSize, 1> myFunc();

template <>
Eigen::Matrix<double, 2, 1> myFunc<2>()
{
    return ExternalLibrary::generate_Vector_2d();
}

template <>
Eigen::Matrix<double, 3, 1> myFunc<3>()
{
    return ExternalLibrary::generate_Vector_3d();
}

编译器虽然它会消除死代码作为优化,仍然必须验证死代码的有效性,这意味着它必须确保ExternalLibrary::generate_Vector_3d()的返回类型可以是转换为Eigen::Matrix<double, 2, 1>,即使可以证明无法执行该return语句。因为不允许这种转换,所以会出现编译时错误。

通过将两个return语句分离为单独的特化,可以消除此问题,因为它从可能返回除return ExternalLibrary::generate_Vector_3d();以外的函数的函数中删除Eigen::Matrix<double, 3, 1>语句

请注意,myFunc()使用nSize而不是2或3会导致链接时错误。我们可以通过提供一个无法实例化的主体将此错误移动到编译时,但(表面上)依赖于nSize,以便编译器在使用之前不会尝试实例化它:

template <int nSize>
Eigen::Matrix<double, nSize, 1> myFunc()
{
    // With C++11, the following line provides a more useful diagnostic. If
    // you don't have C++11 support, remove it and the bad return statement
    // will do the job, albeit with a more cryptic error message.
    static_assert((static_cast<void>(nSize), false), "Invalid template parameter nSize");

    return static_cast<class INVALID_NSIZE_PARAMETER**********>(nSize);
}

这将提供指向myFunc()错误使用的诊断。例如,如果没有C ++ 11支持,您会看到类似的内容:

main.cpp:12:12: error: cannot cast from type 'int' to pointer type 'class INVALID_NSIZE_PARAMETER **********'
    return static_cast<class INVALID_NSIZE_PARAMETER**********>(nSize);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:29:5: note: in instantiation of function template specialization 'myFunc<4>' requested here
    myFunc<4>();
    ^