【问题标题】:Using conditional statement to select different templated matrix class at run-time使用条件语句在运行时选择不同的模板化矩阵类
【发布时间】:2012-12-06 21:19:36
【问题描述】:

我正在使用 Eigen 线性代数库 (link) 中的模板化 Matrix 类。 Matrix 类采用三个名义模板参数:

Matrix<type, rows, cols>

在上面,type 的示例是doublestd::complex&lt;double&gt;。另外,rows是行数,cols是Matrix的列数。

如下面的代码所示,我想做的是在运行时使用条件语句使用不同的模板化 Matrix 类。

想到的第一个解决方案可能是使用 void 指针。

#include <iostream>
#include <Eigen/Dense>
#include <complex>

using namespace Eigen;

int main()

{  
    // this flag is set at run-time, but it is only set here
    // in the code as an example
    int create_complex = 1;
    void *M;

        if(create_complex)
    {
        Matrix<std::complex<double>,3,3> m0;
        M = &m0;
    }
    else
    {
        Matrix<double,3,3> m0;
        M = &m0;
    }
    // de-reference pointer here and use it    

 return 0;
}

虽然此代码可以编译,但 void *M 指针需要在使用前显式取消引用。这很不方便,因为我必须为相同的程序逻辑编写不同的代码块。

我想知道这里是否可以应用类似于多态性的东西,我不必使用 void 指针。

【问题讨论】:

  • create_complex 标志在编译时是未知的。我只是以create_complex 为例。
  • 您介意使用boost::variant 吗?我会非常努力地避免陷入您的境地(也许更多的背景知识会帮助我们帮助您),但如果必须,我会接受。
  • @AlexandreC.:当然,我想使用boost::variant。我以前使用过 boost 库,但我不能说我听说过那个特定的容器。这似乎很有趣。我该如何使用它?
  • Boost 变体将允许您定义一种可以存储任一 Matrix 或Matrix, n, m> 的类型.这样,您就不需要指向 void 的指针。同样,可能有更好的方法来编写代码。
  • 谢谢,Alexandre C. Boost 变体确实非常好。万岁提升!

标签: c++ templates pointers eigen


【解决方案1】:

您可以根据矩阵类型将自己的函数编写为模板,并在条件句中调用不同版本的函数。

这是唯一的方法,因为模板用于在编译时生成代码。您必须在编译时生成所有代码路径,然后选择其中一个。

【讨论】:

    【解决方案2】:

    这很不方便

    如果您将“不方便”理解为“非法”,那么您就对了。

    局部变量在其作用域结束时被销毁(即关闭 }),因此您只剩下一个悬空指针。因此,当您尝试取消引用它时会遇到未定义的行为。

    没有简单的方法可以做到这一点,因为Matrix&lt;std::complex&lt;double&gt;,3,3&gt;Matrix&lt;double,3,3&gt; 是完全不相关的类。我再说一遍。 它们是完全不相关的类

    另一种方法是Matrix 有一个基本类型,并且你有一个指向它的指针,但是你需要动态分配。比如:

    BaseMatrix* m;
    if ()
        m = new Matrix<std::complex<double>,3,3>;
    else 
        m = new Matrix<double,3,3>;
    

    【讨论】:

    • @Lucian:谢谢,Lucian;这是有道理的。
    【解决方案3】:

    你也应该模板化你的方法:

    template<class T>
    my_main() { 
    
       Matrix<T,3,3> m0;
    
       // ...
    
    
    }
    

    更新

    或者你可以定义你的类

    #ifndef CREATE_COMPLEX
        typedef double MyClass;
    #else
        typedef std::complex<double> MyClass;
    #endif
    
    main() { 
    
       Matrix<MyClass,3,3> m0;
    
       // ...
    
    
    }
    

    您可以使用预处理器定义切换这些定义。

    【讨论】:

    • 当然,该方法可以模板化,然后我就不必处理 void 指针了。谢谢,迪姆斯。
    猜你喜欢
    • 2018-01-12
    • 1970-01-01
    • 2011-07-20
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    相关资源
    最近更新 更多