c ++ templatizing类构造函数

时间:2018-01-23 04:26:53

标签: c++

我有一个类,它有一个构造函数,它有很多参数

enum class FooType {FOO_A, FOO_B, FOO_C};

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

取决于'类型',我只需要某个参数的子集。目前有各种构造函数具有不同数量的输入,但是将添加一些新类型以使输入的数量相同。我可以将类型添加到构造函数中,在其中有一个长开关,但params列表很长。

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

注意:我不想使用继承,因为课程的其他部分&#39;功能完全没有用/需要它。

2 个答案:

答案 0 :(得分:3)

这可能是命名参数idiom的用例: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();

除了上面的例子,你可以有一个包含所有命名参数的辅助类,你的类构造函数会将参数类的一个实例作为参数。

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

答案 1 :(得分:1)

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

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语句中执行的代码,您可以在构建器的构造函数或build的{​​{1}}实例上执行你会回来的。

示例Fooa相关,FOO_Ab相关,FOO_Bc相关,其他值已初始化到他们的默认值。

这就是你如何使用它:

FOO_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; } 形式的任何构建器专门化添加另一个参数(它应返回自引用,以便可以链接这些功能)。