C++模板问题,将构建器模式拉到配置中

C++ template issue to Pull Up the Builder pattern into a configuration?

本文关键字:模式 配置 构建 问题 C++      更新时间:2023-10-16

我有一个算法,需要大量的参数(即配置(作为其构造函数的一部分,还需要一些明确定义的创建步骤。因此,我创建了一个构建器模式实现,它允许设置所需的参数并创建中间和最终实例,例如

// somewhere
class SomeAlgo { 
    public:
       SomeAlgo(double a, double b, double c, double d, double e /* etc */);
;

现在我将构建器定义为例如

class SomeAlgoBuilder {
    public:
      SomeAlgo& createResult() { /* TODO: */ }
      virtual SomeAlgoBuilder& creationStep1() = 0;
      virtual SomeAlgoBuilder& creationStep2() = 0;
      virtual SomeAlgoBuilder& creationStep3() = 0;
      // example setter note the builder returns *this
      SomeAlgoBuilder& setA(double a) { a_ = a; return *this; } 
      SomeAlgoBuilder& setB(double b) { b_ = b; return *this; } 
      // etc 
};

在这一点上,一切看起来都不错,但现在我想将构建器的 setter Pull Up到一个 SomeAlgoConfig 类中,以便我还可以涵盖传递简单配置而不是复杂的长参数列表的用例。这种简单的配置在Java中被称为值对象或Bean。新的生成器将是这样的:

// not "is a" config but need the implementation inheritance 
// >>>>>> note the need to pass SomeAlgoBuilder as template
class SomeAlgoBuilder : private SomeAlgoConfig<SomeAlgoBuilder> {
    public:
      SomeAlgo& createResult() { /* TODO: */ }
      virtual SomeAlgoBuilder& creationStep1() = 0;
      virtual SomeAlgoBuilder& creationStep2() = 0;
      virtual SomeAlgoBuilder& creationStep3() = 0;
};

现在SomeAlgoConfig实现:

template<T>  
class SomeAlgoConfig {
      T& setA(double a) { a_ = a; return *static_cast<T*>(this); } 
      T& setB(double b) { b_ = b; return *static_cast<T*>(this); } 
      // etc 
}

意图是像这样使用:

SomeAlgoConfig config; // <<< here it won't compile because it misses the T parameter
config.setA(a).setB(b).setC(c);

我猜这会起作用。但是,每当我想单独使用SomeAlgoConfig(在构建器的上下文之外(时,例如将其作为参数传递,我需要使用模板参数声明它,该模板参数本身将SomeAlgoConfig<SomeAlgoConfig>。如何以默认为模板类型的方式定义它?例如,这样做不起作用:template<typename T = SomeAlgoConfig> class SomeAlgoConfig因为此时SomeAlgoConfig还不知道。

Config 应该像参数的容器,因此当您改变对要传递的参数的想法时,您不必更改构造函数和 setter。 让构建器继承配置是没有意义的,因为生成器不是配置,"我需要继承的方法"不是在设计中实现这一点的有效参数。您可以将 config 作为构建器的成员并调用:

builder.getConfig().setA(a);
builder.getConfig().setB(b);
//...
builder.createResult();

如果你想要一个模板配置,你也可以制作构建器模板,例如:

template<class T>
class AlgoBuilder<T>{
//...
private:
AlgoConfig<T> config;

这样,您就可以在构造函数中设置传递配置。

关于您在实例化配置时缺少 T 参数的问题......那么,在这一点上,由于您要设置 a、b 、c 和所有其他参数,您已经知道参数的类型,因此您实际上可以使用 T 类型实例化配置,这与参数类型相同。AlgoConfig对我来说没有多大意义。