简体   繁体   English

C ++模板化类构造函数

[英]c++ templatizing class constructor

I have a class that has a constructor taking quite a few parameters 我有一个类,它的构造函数带有很多参数

enum class FooType {FOO_A, FOO_B, FOO_C};

class Foo {
    Foo(const double a, const double b, .... const double n);
}

depending on the 'type', I only need a certain subset of the params. 根据“类型”,我只需要参数的某个子集。 At the moment there are various constructors with different number of inputs, but some new types will be added so that the number of inputs is the same. 目前,有各种构造函数的输入数量不同,但是将添加一些新类型,以使输入数量相同。 I could just add the type to the constructor, have a long switch in it, but the params list is quite long. 我可以将类型添加到构造函数中,在其中进行很长的切换,但是params列表很长。

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

}

Doesn't seem too bad, but I also don't like having that long parameter list. 似乎还不错,但是我也不喜欢有那么长的参数列表。 Seems to easy to make typos that are a pain to debug. 似乎很容易产生错字,这是调试的麻烦。 So I can a.) pass a structure in b.) do something else 所以我可以a。)在b。中传递结构)做其他事情

and I am just curious about potential b solutions. 我只是对潜在的b解决方案感到好奇。

Is it possible to templateize this such that I could create a template constructor and call the constructor with something like 是否可以对此进行模板化,以便我可以创建模板构造函数并使用类似以下内容的方式调用构造函数

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

Note: I don't want to use inheritance since the rest of the class' functionality has absolutely no use/need for it. 注意:我不想使用继承,因为该类的其余功能绝对不需要/不需要它。

This could be a use case for the named parameters idiom: http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-parameter-idiom.html . 这可能是命名参数惯用法的用例: http : //www.cs.technion.ac.il/users/yechiel/c++-faq/named-parameter-idiom.html

That would allow your constructor call to look like this: 那将使您的构造函数调用看起来像这样:

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

Instead of the above example, you could have a helper class that contains all the named parameters and your class constructor would take an instance of the parameters class as its parameters. 代替上面的示例,您可以有一个包含所有已命名参数的帮助程序类,并且您的类构造函数将参数类的实例作为其参数。

This lets you freely pick the set of parameters that you initialize at construction time. 这使您可以自由选择在构造时初始化的参数集。 If you want to enforce different subsets being initialized for the different types, then you should just write different constructor versions. 如果要强制为不同类型初始化不同的子集,则应只编写不同的构造函数版本。

Here is how you could make a templated constructor using a builder pattern: 这是使用构建器模式制作模板化构造函数的方法:

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 }; }
};

The Builder class is templated as you wanted and the code you were executing in that if else statement, you can execute in builder's constructor or the build function on the instance of Foo you will be returning. 可以根据需要对Builder类进行模板化,并在if语句中执行代码,您可以在builder的构造函数中执行,也可以在要返回的Foo实例上的build函数中执行。

In the example a is relevant for FOO_A , b is relevant for FOO_B and c for FOO_C and other values get initialized to their default value. 在示例中, aFOO_A有关, bFOO_B有关, cFOO_C ,其他值被初始化为其默认值。

This is how you would use it: 这是您将如何使用它:

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;
}

It is a pretty small example for a builder pattern, but from your example it seems like you are using much more arguments. 对于构建器模式而言,这是一个很小的示例,但是从您的示例中看来,您正在使用更多的参数。 To add another argument to any of the builder specializations in form Builder& typeName(Type val) { _typeName = val; return *this; } 要以格式Builder& typeName(Type val) { _typeName = val; return *this; } Builder& typeName(Type val) { _typeName = val; return *this; } Builder& typeName(Type val) { _typeName = val; return *this; } (it should return self reference so these funtions can be chained). Builder& typeName(Type val) { _typeName = val; return *this; } (它应该返回自我引用,以便可以链接这些功能)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM