【问题标题】:C++ factory of a class that specializes a templated superclass专门化模板化超类的类的 C++ 工厂
【发布时间】:2021-10-15 15:05:13
【问题描述】:

我正在开发一个用于数学优化的 C++ 框架,并且我正在努力为我的稀疏矩阵表示找到一个好的设计。
基本上:

  • 我有两种稀疏矩阵表示:类型 A 和 B;
  • 我有(比如说)四个线性求解器,Alan、Alicia、Beth 和 Benjamin。 Alan 和 Alicia 专门使用 A 矩阵,Beth 和 Benjamin 使用 B 矩阵;
  • 我想对我的代码进行模板化,以便在运行时选择线性求解器在其余代码中设置所有矩阵的类型(A 或 B 型)(从而直接生成线性系统的矩阵格式正确)。

我尝试了以下(简化的)代码:

template <class MatrixType>
class LinearSolver {
   virtual void factorize(const MatrixType& matrix) = 0;
}

class LinearSolverAlan: public LinearSolver<MatrixTypeA> {
   void factorize(const MatrixTypeA& matrix) override;
}

class LinearSolverAlicia: public LinearSolver<MatrixTypeA> {
   void factorize(const MatrixTypeA& matrix) override;
}

class LinearSolverBeth: public LinearSolver<MatrixTypeB> {
   void factorize(const MatrixTypeB& matrix) override;
}

class LinearSolverBenjamin: public LinearSolver<MatrixTypeB> {
   void factorize(const MatrixTypeB& matrix) override;
}

求解器的常见超类型是模板类型LinearSolver,所以我也对工厂进行了模板化:

template<class MatrixType>
class LinearSolverFactory {
public:
   std::unique_ptr<LinearSolver<MatrixType> > create(const std::string& solver_name) {
     if (solver_name == "alan") {
        return std::make_unique<LinearSolverAlan>();
     }
     else if (...) {
        ...
     }
   }
};

然后在更高级别上,我使用正确的求解器名称和模板参数调用 LinearSolverFactory::create()

但是它不会编译(std::unique_ptr&lt;LinearSolverAlan&gt; 不能转换为std::unique_ptr&lt;LinearSolver&lt;MatrixTypeA&gt; &gt;)。我的模板不够好,看问题能否解决。

感谢您的帮助:)

查理

【问题讨论】:

  • 两个分支都必须有效,但同时只有一个。为什么要通过模板参数和字符串参数选择哪种类型?其中一个是否足以决定工厂应该返回哪种类型的求解器?
  • 感谢您的回复。线性求解器是第三方代码,可能超过 2 个。它们每个都使用 A 或 B 矩阵。这就是我给他们起名字的原因;我们选择求解器,它反过来应该修复矩阵类型。
  • 但是只能调用LinearSolverFactory&lt;TypeA&gt;::create("alan")而且只能调用LinearSolverFactory&lt;TypeB&gt;::create("beth"),字符串好像是多余的,还是我误会了什么?
  • 模板和类型是编译时的事情。根据求解器的运行时选择,您不能将“未知”类型的矩阵转换为正确的矩阵类型。您可以在编译时做出选择,并且可以丢弃带有名称的字符串。或者您可以在运行时做出选择,并使用多态性。
  • super 说了什么,但是您已经在编译时通过模板参数选择了矩阵类型。也许添加一个您计划如何使用工厂的示例将有助于澄清

标签: c++ templates inheritance matrix factory


【解决方案1】:

LinearSolverAlanLinearSolverBeth 不共享一个共同的基础,因为 LinearSolver&lt;MatrixTypeA&gt;LinearSolver&lt;MatrixTypeB&gt; 是两个不相关的类型。

您可以使用if constexpr 来丢弃工厂特定实例化中未使用的分支或专门化整个工厂:

template <typename MatrixType>
struct Factory;

template <> 
struct Factory<MatrixTypeA> {
   std::unique_ptr<LinearSolver<MatrixTypeA> > create(const std::string& name) {
         // select a LinearSolve<MatrixTypeA> and return it
   }
};

template <> 
struct Factory<MatrixTypeB> {
   std::unique_ptr<LinearSolver<MatrixTypeB> > create(const std::string& name) {
         // select a LinearSolver<MatrixTypeB> and return it
   }
};

另一种选择是让LinearSolver&lt;MatrixTypeB&gt;LinearSovler&lt;MatrixTypeB&gt; 继承自一个通用(非模板)基类。

【讨论】:

  • 漂亮!专业工厂成功了,非常感谢。
猜你喜欢
  • 2013-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-02
  • 1970-01-01
  • 1970-01-01
  • 2014-10-01
  • 2015-06-15
相关资源
最近更新 更多