C++ 模板化类构造函数

c++ templatizing class constructor

本文关键字:构造函数 C++      更新时间:2023-10-16

>我有一个类,它有一个构造函数,需要相当多的参数

enum class FooType {FOO_A, FOO_B, FOO_C};
class Foo {
    Foo(const double a, const double b, .... const double n);
}

根据"类型",我只需要参数的特定子集。目前有各种构造函数具有不同数量的输入,但将添加一些新类型,以便输入数量相同。我可以将类型添加到构造函数中,在其中有一个长开关,但参数列表很长。

Foo(FooType type, const double a, const double b, .... const double n) {
    if (type = FooType::FOO_A) {
        ...
    } else if ....
}

看起来还不错,但我也不喜欢有那么长的参数列表。似乎很容易使错别字难以调试。所以我可以a.)传入结构b.)做点别的

我只是对潜在的 b 解决方案感到好奇。

是否可以对此进行模板化,以便我可以创建一个模板构造函数并使用类似的东西调用构造函数

std::make_shared<Foo<FooType::FOO_A>>(a, b, c);

注意:我不想使用继承,因为类的其余功能完全没有用处/不需要它。

这可能是命名参数习语的用例:http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-parameter-idiom.html .

这将允许构造函数调用如下所示:

File f = OpenFile("foo.txt")
           .readonly()
           .createIfNotExist()
           .appendWhenWriting()
           .blockSize(1024)
           .unbuffered()
           .exclusiveAccess();

您可以有一个包含所有命名参数的帮助程序类,而不是上面的示例,并且您的类构造函数将采用参数类的实例作为其参数。

这使您可以自由选择在构造时初始化的参数集。如果要强制为不同类型的初始化不同的子集,则应编写不同的构造函数版本。

以下是使用构建器模式创建模板化构造函数的方法:

class Foo {
    double a;
    int b;
    double c;
public:
    Foo(double a, int b, char c) {
    }
};
template <FooType Type>
class Builder { };
template <>
class Builder<FooType::FOO_A> {
    double _a;
public:
    Builder& a(double val) { _a = val; return *this; }
    Foo build() { return { _a, 0, 0 }; }
};
template <>
class Builder<FooType::FOO_B> {
    int _b;
public:
    Builder& b(int val) { _b = val; return *this; }
    Foo build() { return { 0.0, _b, 0 }; }
};
template <>
class Builder<FooType::FOO_C> {
    char _c;
public:
    Builder& c(char val) { _c = val; return *this; }
    Foo build() { return { 0.0, 0, _c }; }
};

Builder类是根据需要模板化的,您在 if else 语句中执行的代码,您可以在构建器的构造函数或您将返回的Foo实例上的 build 函数中执行。

在示例中,aFOO_A相关,bFOO_B相关,cFOO_C相关,其他值被初始化为其默认值。

这是您将如何使用它:

int main() {
    Foo testA = Builder<FooType::FOO_A>().a(12.5).build();
    Foo testB = Builder<FooType::FOO_B>().b(10).build();
    Foo testC = Builder<FooType::FOO_C>().c('x').build();
    return 0;
}

对于构建器模式来说,这是一个非常小的示例,但从您的示例中,您似乎使用了更多的参数。向表单 Builder& typeName(Type val) { _typeName = val; return *this; } 中的任何构建器专用化添加另一个参数(它应返回自引用,以便可以链接这些功能(。